Skip to content

Commit 79d5df1

Browse files
Merge branch 'develop' into fix/reactive-display-name-disambiguation
2 parents a389c91 + fb59062 commit 79d5df1

21 files changed

+557
-431
lines changed

.github/workflows/notify-downstream.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
runs-on: ubuntu-24.04
2020
steps:
2121
- name: Notify matrix-react-sdk repo that a new SDK build is on develop so it can CI against it
22-
uses: peter-evans/repository-dispatch@5fc4efd1a4797ddb68ffd0714a238564e4cc0e6f # v4
22+
uses: peter-evans/repository-dispatch@28959ce8df70de7be546dd1250a005dd32156697 # v4
2323
with:
2424
token: ${{ secrets.ELEMENT_BOT_TOKEN }}
2525
repository: ${{ matrix.repo }}

.github/workflows/sonarcloud.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
steps:
2828
# We create the status here and then update it to success/failure in the `report` stage
2929
# This provides an easy link to this workflow_run from the PR before Sonarcloud is done.
30-
- uses: guibranco/github-status-action-v2@5530c593759f489bba08272e96986ffc571c1ea1
30+
- uses: guibranco/github-status-action-v2@9bfa8773cdbdc6c185747fd43cd7faa9d7c32f09
3131
with:
3232
authToken: ${{ secrets.GITHUB_TOKEN }}
3333
state: pending
@@ -88,7 +88,7 @@ jobs:
8888
revision: ${{ github.event.workflow_run.head_sha }}
8989
token: ${{ secrets.SONAR_TOKEN }}
9090

91-
- uses: guibranco/github-status-action-v2@5530c593759f489bba08272e96986ffc571c1ea1
91+
- uses: guibranco/github-status-action-v2@9bfa8773cdbdc6c185747fd43cd7faa9d7c32f09
9292
if: always()
9393
with:
9494
authToken: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ jobs:
112112
steps:
113113
- name: Skip SonarCloud on merge queues
114114
if: env.ENABLE_COVERAGE == 'false'
115-
uses: guibranco/github-status-action-v2@5530c593759f489bba08272e96986ffc571c1ea1
115+
uses: guibranco/github-status-action-v2@9bfa8773cdbdc6c185747fd43cd7faa9d7c32f09
116116
with:
117117
authToken: ${{ secrets.GITHUB_TOKEN }}
118118
state: success

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@
110110
"knip": "^5.0.0",
111111
"lint-staged": "^16.0.0",
112112
"matrix-mock-request": "^2.5.0",
113-
"prettier": "3.8.0",
113+
"prettier": "3.8.1",
114114
"rimraf": "^6.0.0",
115115
"typedoc": "^0.28.1",
116116
"typedoc-plugin-coverage": "^4.0.0",

spec/unit/matrix-client.spec.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3877,6 +3877,27 @@ describe("MatrixClient", function () {
38773877
makeClient();
38783878
});
38793879

3880+
it("should use stable prefix", async () => {
3881+
const metadata = mockOpenIdConfiguration();
3882+
client.getVersions = vi.fn().mockResolvedValue({
3883+
versions: ["v1.15"],
3884+
});
3885+
httpLookups = [
3886+
{
3887+
method: "GET",
3888+
path: `/auth_metadata`,
3889+
data: metadata,
3890+
prefix: "/_matrix/client/v1",
3891+
},
3892+
];
3893+
3894+
await expect(client.getAuthMetadata()).resolves.toEqual({
3895+
...metadata,
3896+
signingKeys: [],
3897+
});
3898+
expect(httpLookups.length).toEqual(0);
3899+
});
3900+
38803901
it("should use unstable prefix", async () => {
38813902
const metadata = mockOpenIdConfiguration();
38823903
httpLookups = [

spec/unit/matrixrtc/CallMembership.spec.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,10 @@ describe("CallMembership", () => {
158158
expect(membership.eventId).toBe("$eventid");
159159
});
160160
it("returns correct slot_id", () => {
161-
expect(membership.slotId).toBe("m.call#");
162-
expect(membership.slotDescription).toStrictEqual({ id: "", application: "m.call" });
161+
// for legacy events we expect the room to be added automagically
162+
// See INFO_SLOT_ID_LEGACY_CASE comments
163+
expect(membership.slotId).toBe("m.call#ROOM");
164+
expect(membership.slotDescription).toStrictEqual({ id: "ROOM", application: "m.call" });
163165
});
164166
it("returns correct deviceId", () => {
165167
expect(membership.deviceId).toBe("AAAAAAA");

spec/unit/matrixrtc/MatrixRTCSession.spec.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ const mockFocus = { type: "mock" };
4949

5050
const textEncoder = new TextEncoder();
5151

52-
const callSession = { id: "", application: "m.call" };
52+
const callSession = { id: "ROOM", application: "m.call" };
5353

5454
describe("MatrixRTCSession", () => {
5555
let client: MatrixClient;
@@ -134,12 +134,12 @@ describe("MatrixRTCSession", () => {
134134
);
135135
await flushPromises();
136136
expect(sess?.memberships.length).toEqual(1);
137-
expect(sess?.memberships[0].slotDescription.id).toEqual("");
137+
expect(sess?.memberships[0].slotDescription.id).toEqual("ROOM");
138138
expect(sess?.memberships[0].scope).toEqual("m.room");
139139
expect(sess?.memberships[0].application).toEqual("m.call");
140140
expect(sess?.memberships[0].deviceId).toEqual("AAAAAAA");
141141
expect(sess?.memberships[0].isExpired()).toEqual(false);
142-
expect(sess?.slotDescription.id).toEqual("");
142+
expect(sess?.slotDescription.id).toEqual("ROOM");
143143
});
144144

145145
it("ignores memberships where application is not m.call", () => {
@@ -381,12 +381,12 @@ describe("MatrixRTCSession", () => {
381381
});
382382
await flushPromises();
383383
expect(sess?.memberships.length).toEqual(1);
384-
expect(sess?.memberships[0].slotDescription.id).toEqual("");
384+
expect(sess?.memberships[0].slotDescription.id).toEqual("ROOM");
385385
expect(sess?.memberships[0].scope).toEqual("m.room");
386386
expect(sess?.memberships[0].application).toEqual("m.call");
387387
expect(sess?.memberships[0].deviceId).toEqual("AAAAAAA");
388388
expect(sess?.memberships[0].isExpired()).toEqual(false);
389-
expect(sess?.slotDescription.id).toEqual("");
389+
expect(sess?.slotDescription.id).toEqual("ROOM");
390390
});
391391
it("combines sticky and membership events when both exist", async () => {
392392
// Create a room with identical member state and sticky state for the same user.
@@ -415,7 +415,7 @@ describe("MatrixRTCSession", () => {
415415
const memberships = sess.memberships;
416416
expect(memberships.length).toEqual(2);
417417
expect(memberships[0].sender).toEqual(stickyUserId);
418-
expect(memberships[0].slotDescription.id).toEqual("");
418+
expect(memberships[0].slotDescription.id).toEqual("ROOM");
419419
expect(memberships[0].scope).toEqual("m.room");
420420
expect(memberships[0].application).toEqual("m.call");
421421
expect(memberships[0].deviceId).toEqual("AAAAAAA");
@@ -424,7 +424,7 @@ describe("MatrixRTCSession", () => {
424424
// Then state
425425
expect(memberships[1].sender).toEqual(membershipTemplate.user_id);
426426

427-
expect(sess?.slotDescription.id).toEqual("");
427+
expect(sess?.slotDescription.id).toEqual("ROOM");
428428
});
429429
it("handles an incoming sticky event to an existing session", async () => {
430430
const mockRoom = makeMockRoom([membershipTemplate]);

spec/unit/matrixrtc/MembershipManager.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ function createAsyncHandle<T>(method: MockedFunction<(...args: any[]) => any>) {
7171
return { reject, resolve };
7272
}
7373

74-
const callSession = { id: "", application: "m.call" };
74+
const callSession = { id: "ROOM", application: "m.call" };
7575

7676
describe("MembershipManager", () => {
7777
let client: MockClient;
@@ -969,7 +969,7 @@ describe("MembershipManager", () => {
969969
id: "@alice:example.org:AAAAAAA_m.call",
970970
device_id: "AAAAAAA",
971971
},
972-
slot_id: "m.call#",
972+
slot_id: "m.call#ROOM",
973973
rtc_transports: [{ type: focus.type, livekit_service_url: focus.livekit_service_url }],
974974
versions: [],
975975
msc4354_sticky_key: "@alice:example.org:AAAAAAA_m.call",

spec/unit/room-upgrade.spec.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
Copyright 2026 The Matrix.org Foundation C.I.C.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
import { MatrixClient } from "../../src/client";
18+
19+
describe("Room upgrades", function () {
20+
it("Sends an HTTP request upgrading the room", () => {
21+
// Given a client with a fake authedRequest method
22+
const { client, authedRequest } = createClient();
23+
24+
// When we upgrade the room to version 12
25+
client.upgradeRoom("!r1", "12");
26+
27+
// Then we make an HTTP request to the correct endpoint, with the
28+
// version provided in the JSON.
29+
expect(authedRequest).toHaveBeenCalledWith("POST", "/rooms/!r1/upgrade", undefined, { new_version: "12" });
30+
});
31+
32+
it("Includes additional_creators if provided", () => {
33+
// Given a client with a fake authedRequest method
34+
const { client, authedRequest } = createClient();
35+
36+
// When we upgrade the room to version 13 and supply additionalCreators
37+
client.upgradeRoom("!r1", "13", ["@u:s.co", "@v:a.b"]);
38+
39+
// Then we make an HTTP request to the correct endpoint, with the
40+
// version and additional creators provided.
41+
expect(authedRequest).toHaveBeenCalledWith("POST", "/rooms/!r1/upgrade", undefined, {
42+
new_version: "13",
43+
additional_creators: ["@u:s.co", "@v:a.b"],
44+
});
45+
});
46+
});
47+
48+
///
49+
function createClient(): { client: MatrixClient; authedRequest: any } {
50+
const authedRequest = vi.fn();
51+
const client = new MatrixClient({
52+
baseUrl: "https://my.home.server",
53+
userId: "@u:s.co",
54+
});
55+
client.http.authedRequest = authedRequest;
56+
return { client, authedRequest };
57+
}

src/@types/event.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ export enum EventType {
138138
PushRules = "m.push_rules",
139139
Direct = "m.direct",
140140
IgnoredUserList = "m.ignored_user_list",
141+
InvitePermissionConfig = "m.invite_permission_config", // MSC4380
141142

142143
// to_device events
143144
RoomKey = "m.room_key",
@@ -404,6 +405,8 @@ export interface AccountDataEvents extends SecretStorageAccountDataEvents {
404405
// Invites-ignorer events
405406
[POLICIES_ACCOUNT_EVENT_TYPE.name]: { [key: string]: any };
406407
[POLICIES_ACCOUNT_EVENT_TYPE.altName]: { [key: string]: any };
408+
409+
[EventType.InvitePermissionConfig]: { default_action?: string };
407410
}
408411

409412
/**

0 commit comments

Comments
 (0)