Skip to content

Commit de4e9d1

Browse files
committed
Merge tag 'v15.1.0' into sc
* Mark old verification methods as deprecated ([\matrix-org#1994](matrix-org#1994)). * Try to set a sender on search result events if possible ([\matrix-org#2004](matrix-org#2004)). * Port some changes from group calls branch to develop ([\matrix-org#2001](matrix-org#2001)). Contributed by @SimonBrandner. * Fetch room membership from server rather than relying on stored data ([\matrix-org#1998](matrix-org#1998)). * Add method to fetch the MSC3266 Room Summary of a Room ([\matrix-org#1988](matrix-org#1988)). * Don't show `Unable to access microphone` when cancelling screensharing dialog ([\matrix-org#2005](matrix-org#2005)). Fixes element-hq/element-web#19533 and element-hq/element-web#19533. Contributed by @SimonBrandner. * Strip direction override characters from display names ([\matrix-org#1992](matrix-org#1992)). Fixes element-hq/element-web#1712 and element-hq/element-web#1712.
2 parents 15f60b1 + 9fb4fed commit de4e9d1

File tree

11 files changed

+530
-312
lines changed

11 files changed

+530
-312
lines changed

CHANGELOG.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,35 @@
1+
Changes in [15.1.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v15.1.0) (2021-11-08)
2+
==================================================================================================
3+
4+
## 🦖 Deprecations
5+
* Mark old verification methods as deprecated ([\#1994](https://github.com/matrix-org/matrix-js-sdk/pull/1994)).
6+
7+
## ✨ Features
8+
* Try to set a sender on search result events if possible ([\#2004](https://github.com/matrix-org/matrix-js-sdk/pull/2004)).
9+
* Port some changes from group calls branch to develop ([\#2001](https://github.com/matrix-org/matrix-js-sdk/pull/2001)). Contributed by @SimonBrandner.
10+
* Fetch room membership from server rather than relying on stored data ([\#1998](https://github.com/matrix-org/matrix-js-sdk/pull/1998)).
11+
* Add method to fetch the MSC3266 Room Summary of a Room ([\#1988](https://github.com/matrix-org/matrix-js-sdk/pull/1988)).
12+
13+
## 🐛 Bug Fixes
14+
* 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.
15+
* 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.
16+
17+
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)
18+
============================================================================================================
19+
20+
## 🦖 Deprecations
21+
* Mark old verification methods as deprecated ([\#1994](https://github.com/matrix-org/matrix-js-sdk/pull/1994)).
22+
23+
## ✨ Features
24+
* Try to set a sender on search result events if possible ([\#2004](https://github.com/matrix-org/matrix-js-sdk/pull/2004)).
25+
* Port some changes from group calls branch to develop ([\#2001](https://github.com/matrix-org/matrix-js-sdk/pull/2001)). Contributed by @SimonBrandner.
26+
* Fetch room membership from server rather than relying on stored data ([\#1998](https://github.com/matrix-org/matrix-js-sdk/pull/1998)).
27+
* Add method to fetch the MSC3266 Room Summary of a Room ([\#1988](https://github.com/matrix-org/matrix-js-sdk/pull/1988)).
28+
29+
## 🐛 Bug Fixes
30+
* 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.
31+
* 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.
32+
133
Changes in [15.0.0](https://github.com/vector-im/element-desktop/releases/tag/v15.0.0) (2021-10-25)
234
===================================================================================================
335

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "matrix-js-sdk",
3-
"version": "15.0.0",
3+
"version": "15.1.0",
44
"description": "Matrix Client-Server SDK for Javascript",
55
"scripts": {
66
"prepublishOnly": "yarn build",
@@ -81,7 +81,7 @@
8181
"@types/request": "^2.48.5",
8282
"@typescript-eslint/eslint-plugin": "^4.17.0",
8383
"@typescript-eslint/parser": "^4.17.0",
84-
"allchange": "^1.0.2",
84+
"allchange": "^1.0.5",
8585
"babel-jest": "^26.6.3",
8686
"babelify": "^10.0.0",
8787
"better-docs": "^2.4.0-beta.9",

src/client.ts

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,12 @@ interface IThirdPartyUser {
671671
protocol: string;
672672
fields: object;
673673
}
674+
675+
interface IRoomSummary extends Omit<IPublicRoomsChunkRoom, "canonical_alias" | "aliases"> {
676+
room_type?: RoomType;
677+
membership?: string;
678+
is_encrypted: boolean;
679+
}
674680
/* eslint-enable camelcase */
675681

676682
/**
@@ -1749,6 +1755,7 @@ export class MatrixClient extends EventEmitter {
17491755
* @param {string} deviceId the device to verify
17501756
*
17511757
* @returns {Verification} a verification object
1758+
* @deprecated Use `requestVerification` instead.
17521759
*/
17531760
public beginKeyVerification(method: string, userId: string, deviceId: string): Verification {
17541761
if (!this.crypto) {
@@ -1911,6 +1918,7 @@ export class MatrixClient extends EventEmitter {
19111918
return this.crypto.checkCrossSigningPrivateKey(privateKey, expectedPublicKey);
19121919
}
19131920

1921+
// deprecated: use requestVerification instead
19141922
public legacyDeviceVerification(
19151923
userId: string,
19161924
deviceId: string,
@@ -3397,15 +3405,15 @@ export class MatrixClient extends EventEmitter {
33973405
/**
33983406
* @param {string} roomId
33993407
* @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.
3400-
* @param {string} txnId the txnId.
3408+
* @param {string} txnId Optional.
34013409
* @param {module:client.callback} callback Optional.
34023410
* @return {Promise} Resolves: to an empty object {}
34033411
* @return {module:http-api.MatrixError} Rejects: with an error response.
34043412
*/
34053413
private sendCompleteEvent(
34063414
roomId: string,
34073415
eventObject: any,
3408-
txnId: string,
3416+
txnId?: string,
34093417
callback?: Callback,
34103418
): Promise<ISendEventResponse> {
34113419
if (utils.isFunction(txnId)) {
@@ -5414,6 +5422,14 @@ export class MatrixClient extends EventEmitter {
54145422
const resultsLength = roomEvents.results ? roomEvents.results.length : 0;
54155423
for (let i = 0; i < resultsLength; i++) {
54165424
const sr = SearchResult.fromJson(roomEvents.results[i], this.getEventMapper());
5425+
const room = this.getRoom(sr.context.getEvent().getRoomId());
5426+
if (room) {
5427+
// Copy over a known event sender if we can
5428+
for (const ev of sr.context.getTimeline()) {
5429+
const sender = room.getMember(ev.getSender());
5430+
if (!ev.sender && sender) ev.sender = sender;
5431+
}
5432+
}
54175433
searchResults.results.push(sr);
54185434
}
54195435
return searchResults;
@@ -8521,6 +8537,20 @@ export class MatrixClient extends EventEmitter {
85218537
public supportsExperimentalThreads(): boolean {
85228538
return this.clientOpts?.experimentalThreadSupport || false;
85238539
}
8540+
8541+
/**
8542+
* Fetches the summary of a room as defined by an initial version of MSC3266 and implemented in Synapse
8543+
* Proposed at https://github.com/matrix-org/matrix-doc/pull/3266
8544+
* @param {string} roomIdOrAlias The ID or alias of the room to get the summary of.
8545+
* @param {string[]?} via The list of servers which know about the room if only an ID was provided.
8546+
*/
8547+
public async getRoomSummary(roomIdOrAlias: string, via?: string[]): Promise<IRoomSummary> {
8548+
const path = utils.encodeUri("/rooms/$roomid/summary", { $roomid: roomIdOrAlias });
8549+
return this.http.authedRequest(undefined, "GET", path, { via }, null, {
8550+
qsStringifyOptions: { arrayFormat: 'repeat' },
8551+
prefix: "/_matrix/client/unstable/im.nheko.summary",
8552+
});
8553+
}
85248554
}
85258555

85268556
/**

src/models/event-timeline-set.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ interface IOpts {
4444
timelineSupport?: boolean;
4545
filter?: Filter;
4646
unstableClientRelationAggregation?: boolean;
47+
pendingEvents?: boolean;
4748
}
4849

4950
export enum DuplicateStrategy {
@@ -54,6 +55,7 @@ export enum DuplicateStrategy {
5455
export class EventTimelineSet extends EventEmitter {
5556
private readonly timelineSupport: boolean;
5657
private unstableClientRelationAggregation: boolean;
58+
private displayPendingEvents: boolean;
5759
private liveTimeline: EventTimeline;
5860
private timelines: EventTimeline[];
5961
private _eventIdToTimeline: Record<string, EventTimeline>;
@@ -102,6 +104,7 @@ export class EventTimelineSet extends EventEmitter {
102104
this.timelineSupport = Boolean(opts.timelineSupport);
103105
this.liveTimeline = new EventTimeline(this);
104106
this.unstableClientRelationAggregation = !!opts.unstableClientRelationAggregation;
107+
this.displayPendingEvents = opts.pendingEvents !== false;
105108

106109
// just a list - *not* ordered.
107110
this.timelines = [this.liveTimeline];
@@ -151,7 +154,7 @@ export class EventTimelineSet extends EventEmitter {
151154
* @throws If <code>opts.pendingEventOrdering</code> was not 'detached'
152155
*/
153156
public getPendingEvents(): MatrixEvent[] {
154-
if (!this.room) {
157+
if (!this.room || !this.displayPendingEvents) {
155158
return [];
156159
}
157160

src/models/room-member.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,9 @@ export class RoomMember extends EventEmitter {
131131
this.disambiguate,
132132
);
133133

134-
this.rawDisplayName = event.getDirectionalContent().displayname;
134+
// not quite raw: we strip direction override chars so it can safely be inserted into
135+
// blocks of text without breaking the text direction
136+
this.rawDisplayName = utils.removeDirectionOverrideChars(event.getDirectionalContent().displayname);
135137
if (!this.rawDisplayName || !utils.removeHiddenChars(this.rawDisplayName)) {
136138
this.rawDisplayName = this.userId;
137139
}
@@ -355,15 +357,26 @@ function calculateDisplayName(
355357
roomState: RoomState,
356358
disambiguate: boolean,
357359
): string {
358-
if (disambiguate) return displayName + " (" + selfUserId + ")";
360+
if (disambiguate) return utils.removeDirectionOverrideChars(displayName) + " (" + selfUserId + ")";
359361

360362
if (!displayName || displayName === selfUserId) return selfUserId;
361363

362364
// First check if the displayname is something we consider truthy
363365
// after stripping it of zero width characters and padding spaces
364366
if (!utils.removeHiddenChars(displayName)) return selfUserId;
365367

366-
return displayName;
368+
// We always strip the direction override characters (LRO and RLO).
369+
// These override the text direction for all subsequent characters
370+
// in the paragraph so if display names contained these, they'd
371+
// need to be wrapped in something to prevent this from leaking out
372+
// (which we can do in HTML but not text) or we'd need to add
373+
// control characters to the string to reset any overrides (eg.
374+
// adding PDF characters at the end). As far as we can see,
375+
// there should be no reason these would be necessary - rtl display
376+
// names should flip into the correct direction automatically based on
377+
// the characters, and you can still embed rtl in ltr or vice versa
378+
// with the embed chars or marker chars.
379+
return utils.removeDirectionOverrideChars(displayName);
367380
}
368381

369382
/**

src/models/room.ts

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -672,7 +672,13 @@ export class Room extends EventEmitter {
672672
// were the members loaded from the server?
673673
let fromServer = false;
674674
let rawMembersEvents = await this.client.store.getOutOfBandMembers(this.roomId);
675-
if (rawMembersEvents === null) {
675+
// If the room is encrypted, we always fetch members from the server at
676+
// least once, in case the latest state wasn't persisted properly. Note
677+
// that this function is only called once (unless loading the members
678+
// fails), since loadMembersIfNeeded always returns this.membersPromise
679+
// if set, which will be the result of the first (successful) call.
680+
if (rawMembersEvents === null ||
681+
(this.client.isCryptoEnabled() && this.client.isRoomEncrypted(this.roomId))) {
676682
fromServer = true;
677683
rawMembersEvents = await this.loadMembersFromServer();
678684
logger.log(`LL: got ${rawMembersEvents.length} ` +
@@ -1276,19 +1282,23 @@ export class Room extends EventEmitter {
12761282
* Add an event to a thread's timeline. Will fire "Thread.update"
12771283
* @experimental
12781284
*/
1279-
public addThreadedEvent(event: MatrixEvent): void {
1285+
public async addThreadedEvent(event: MatrixEvent): Promise<void> {
12801286
let thread = this.findThreadForEvent(event);
12811287
if (thread) {
12821288
thread.addEvent(event);
12831289
} else {
12841290
const events = [event];
1285-
const rootEvent = this.findEventById(event.threadRootId);
1286-
if (rootEvent) {
1287-
events.unshift(rootEvent);
1291+
let rootEvent = this.findEventById(event.threadRootId);
1292+
// If the rootEvent does not exist in the current sync, then look for
1293+
// it over the network
1294+
if (!rootEvent) {
1295+
const eventData = await this.client.fetchRoomEvent(this.roomId, event.threadRootId);
1296+
rootEvent = new MatrixEvent(eventData);
12881297
}
1298+
events.unshift(rootEvent);
12891299
thread = new Thread(events, this, this.client);
1290-
this.reEmitter.reEmit(thread, [ThreadEvent.Update, ThreadEvent.Ready]);
12911300
this.threads.set(thread.id, thread);
1301+
this.reEmitter.reEmit(thread, [ThreadEvent.Update, ThreadEvent.Ready]);
12921302
this.emit(ThreadEvent.New, thread);
12931303
}
12941304
this.emit(ThreadEvent.Update, thread);

src/models/thread.ts

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,22 @@ export class Thread extends EventEmitter {
3838
/**
3939
* A reference to all the events ID at the bottom of the threads
4040
*/
41-
public readonly timelineSet: EventTimelineSet;
41+
public readonly timelineSet;
4242

4343
constructor(
4444
events: MatrixEvent[] = [],
4545
public readonly room: Room,
4646
public readonly client: MatrixClient,
4747
) {
4848
super();
49-
this.timelineSet = new EventTimelineSet(room, {
49+
if (events.length === 0) {
50+
throw new Error("Can't create an empty thread");
51+
}
52+
53+
this.timelineSet = new EventTimelineSet(this.room, {
5054
unstableClientRelationAggregation: true,
5155
timelineSupport: true,
56+
pendingEvents: false,
5257
});
5358
events.forEach(event => this.addEvent(event));
5459
}
@@ -93,14 +98,6 @@ export class Thread extends EventEmitter {
9398
this.emit(ThreadEvent.Update, this);
9499
}
95100

96-
private async decryptEvents(): Promise<void> {
97-
await Promise.allSettled(
98-
Array.from(this.timelineSet.getLiveTimeline().getEvents()).map(event => {
99-
return this.client.decryptEventIfNeeded(event, {});
100-
}),
101-
);
102-
}
103-
104101
/**
105102
* Finds an event by ID in the current thread
106103
*/
@@ -135,9 +132,13 @@ export class Thread extends EventEmitter {
135132

136133
/**
137134
* The number of messages in the thread
135+
* Only count rel_type=m.thread as we want to
136+
* exclude annotations from that number
138137
*/
139138
public get length(): number {
140-
return this.events.length;
139+
return this.events
140+
.filter(event => event.isThreadRelation)
141+
.length;
141142
}
142143

143144
/**

src/utils.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,18 @@ export function removeHiddenChars(str: string): string {
387387
return "";
388388
}
389389

390+
/**
391+
* Removes the direction override characters from a string
392+
* @param {string} input
393+
* @returns string with chars removed
394+
*/
395+
export function removeDirectionOverrideChars(str: string): string {
396+
if (typeof str === "string") {
397+
return str.replace(/[\u202d-\u202e]/g, '');
398+
}
399+
return "";
400+
}
401+
390402
export function normalize(str: string): string {
391403
// Note: we have to match the filter with the removeHiddenChars() because the
392404
// function strips spaces and other characters (M becomes RN for example, in lowercase).

0 commit comments

Comments
 (0)