From 9136332f42b1b867ef6309b0bd76762117d31a6c Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Tue, 22 Jul 2025 13:25:38 +0000 Subject: [PATCH 01/14] Upgrade dependency to matrix-js-sdk@37.12.0-rc.0 --- package.json | 2 +- yarn.lock | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index fef29cd1f5..d00c6cf32b 100644 --- a/package.json +++ b/package.json @@ -134,7 +134,7 @@ "maplibre-gl": "^5.0.0", "matrix-encrypt-attachment": "^1.0.3", "matrix-events-sdk": "0.0.1", - "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop", + "matrix-js-sdk": "37.12.0-rc.0", "matrix-widget-api": "^1.10.0", "memoize-one": "^6.0.0", "mime": "^4.0.4", diff --git a/yarn.lock b/yarn.lock index 71337815aa..579fb24dff 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4551,13 +4551,14 @@ "@vector-im/matrix-wysiwyg-wasm@link:../../../../Library/Caches/Yarn/v6/npm-@vector-im-matrix-wysiwyg-2.38.4-fb0001dea01010a1e3ffc7042596e2d001ce9389-integrity/node_modules/bindings/wysiwyg-wasm": version "0.0.0" + uid "" "@vector-im/matrix-wysiwyg@2.38.4": version "2.38.4" resolved "https://registry.yarnpkg.com/@vector-im/matrix-wysiwyg/-/matrix-wysiwyg-2.38.4.tgz#fb0001dea01010a1e3ffc7042596e2d001ce9389" integrity sha512-X6ky+1cf33SPdEVd6iTmOKfZZ2mDJv9cz3sHtDhuclS6uitK3QE8td/pmGqBj4ek2Ia4y0mnU61LfxvMry1SMA== dependencies: - "@vector-im/matrix-wysiwyg-wasm" "link:../../../../Library/Caches/Yarn/v6/npm-@vector-im-matrix-wysiwyg-2.38.4-fb0001dea01010a1e3ffc7042596e2d001ce9389-integrity/node_modules/bindings/wysiwyg-wasm" + "@vector-im/matrix-wysiwyg-wasm" "link:../../../.cache/yarn/v6/npm-@vector-im-matrix-wysiwyg-2.38.4-fb0001dea01010a1e3ffc7042596e2d001ce9389-integrity/node_modules/bindings/wysiwyg-wasm" "@vitest/expect@3.0.9": version "3.0.9" @@ -10826,9 +10827,10 @@ matrix-events-sdk@0.0.1: resolved "https://registry.yarnpkg.com/matrix-events-sdk/-/matrix-events-sdk-0.0.1.tgz#c8c38911e2cb29023b0bbac8d6f32e0de2c957dd" integrity sha512-1QEOsXO+bhyCroIe2/A5OwaxHvBm7EsSQ46DEDn8RBIfQwN5HWBpFvyWWR4QY0KHPPnnJdI99wgRiAl7Ad5qaA== -"matrix-js-sdk@github:matrix-org/matrix-js-sdk#develop": - version "37.11.0" - resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/f8f1bf38373a944f12a739a301c1770c7bf08265" +matrix-js-sdk@37.12.0-rc.0: + version "37.12.0-rc.0" + resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-37.12.0-rc.0.tgz#8c439319298a4a74999c9f1cc1222d2799d0f718" + integrity sha512-HFghuEEBgV/ljs34w/Nyqc/E7i1yddopkJdxp6EuerZEeDcJVMi6PbApzLBmbGiRReVzeplmP6yb71g90kTSWw== dependencies: "@babel/runtime" "^7.12.5" "@matrix-org/matrix-sdk-crypto-wasm" "^15.0.0" From acb3d31a076d42e0e3e4149295dcf4f9a3e9434e Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Tue, 22 Jul 2025 13:29:36 +0000 Subject: [PATCH 02/14] v1.11.107-rc.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d00c6cf32b..5de87a38df 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "element-web", - "version": "1.11.106", + "version": "1.11.107-rc.0", "description": "Element: the future of secure communication", "author": "New Vector Ltd.", "repository": { From a23a2c03d3a4fd9bf0b4cc3b57d49053ff9a8a1e Mon Sep 17 00:00:00 2001 From: Robin Date: Sun, 27 Jul 2025 15:37:10 +0200 Subject: [PATCH 03/14] Allow Element Call to send call notifications (#30404) * Allow Element Call to send call notifications Currently Element Web is responsible for sending the call notification event, but this is planned to be changed soon. As of the upcoming Element Call 0.14.0 release, it will request the capability to send call notifications itself, and we should auto-approve this capability. * Add reaction capability missing from test Element Call does in fact request this one. --- src/stores/widgets/StopGapWidgetDriver.ts | 5 +++-- test/unit-tests/stores/widgets/StopGapWidgetDriver-test.ts | 4 ++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/stores/widgets/StopGapWidgetDriver.ts b/src/stores/widgets/StopGapWidgetDriver.ts index 282d6f5d92..d47c9d18e4 100644 --- a/src/stores/widgets/StopGapWidgetDriver.ts +++ b/src/stores/widgets/StopGapWidgetDriver.ts @@ -168,6 +168,7 @@ export class StopGapWidgetDriver extends WidgetDriver { WidgetEventCapability.forStateEvent(EventDirection.Receive, EventType.RoomCreate).raw, ); + const sendRoomEvents = [EventType.CallNotify, EventType.RTCNotification]; const sendRecvRoomEvents = [ "io.element.call.encryption_keys", "org.matrix.rageshake_request", @@ -175,10 +176,10 @@ export class StopGapWidgetDriver extends WidgetDriver { EventType.RoomRedaction, "io.element.call.reaction", ]; - for (const eventType of sendRecvRoomEvents) { + for (const eventType of [...sendRoomEvents, ...sendRecvRoomEvents]) this.allowedCapabilities.add(WidgetEventCapability.forRoomEvent(EventDirection.Send, eventType).raw); + for (const eventType of sendRecvRoomEvents) this.allowedCapabilities.add(WidgetEventCapability.forRoomEvent(EventDirection.Receive, eventType).raw); - } const sendRecvToDevice = [ EventType.CallInvite, diff --git a/test/unit-tests/stores/widgets/StopGapWidgetDriver-test.ts b/test/unit-tests/stores/widgets/StopGapWidgetDriver-test.ts index 1b646498bb..ec352f28d0 100644 --- a/test/unit-tests/stores/widgets/StopGapWidgetDriver-test.ts +++ b/test/unit-tests/stores/widgets/StopGapWidgetDriver-test.ts @@ -92,12 +92,16 @@ describe("StopGapWidgetDriver", () => { "m.always_on_screen", "town.robin.msc3846.turn_servers", "org.matrix.msc2762.timeline:!1:example.org", + "org.matrix.msc2762.send.event:org.matrix.msc4075.call.notify", + "org.matrix.msc2762.send.event:org.matrix.msc4075.rtc.notification", "org.matrix.msc2762.send.event:org.matrix.rageshake_request", "org.matrix.msc2762.receive.event:org.matrix.rageshake_request", "org.matrix.msc2762.send.event:m.reaction", "org.matrix.msc2762.receive.event:m.reaction", "org.matrix.msc2762.send.event:m.room.redaction", "org.matrix.msc2762.receive.event:m.room.redaction", + "org.matrix.msc2762.send.event:io.element.call.reaction", + "org.matrix.msc2762.receive.event:io.element.call.reaction", "org.matrix.msc2762.receive.state_event:m.room.create", "org.matrix.msc2762.receive.state_event:m.room.name", "org.matrix.msc2762.receive.state_event:m.room.member", From db5c69e22899f62ff6f2b5cb9f8a733b61c6cf54 Mon Sep 17 00:00:00 2001 From: ElementRobot Date: Mon, 28 Jul 2025 09:58:20 +0100 Subject: [PATCH 04/14] Fix e2e shield being invisible in white mode for encrypted room (#30408) (#30411) Co-authored-by: Florian Duros --- playwright/e2e/crypto/crypto.spec.ts | 2 ++ .../composer-e2e-icon-normal-linux.png | Bin 0 -> 268 bytes res/css/views/rooms/_E2EIcon.pcss | 8 +++++++- 3 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 playwright/snapshots/crypto/crypto.spec.ts/composer-e2e-icon-normal-linux.png diff --git a/playwright/e2e/crypto/crypto.spec.ts b/playwright/e2e/crypto/crypto.spec.ts index d69af46a72..6d01435546 100644 --- a/playwright/e2e/crypto/crypto.spec.ts +++ b/playwright/e2e/crypto/crypto.spec.ts @@ -158,6 +158,8 @@ test.describe("Cryptography", function () { await page.getByRole("textbox", { name: "Send a message…" }).press("Enter"); await checkDMRoom(page); const bobRoomId = await bobJoin(page, bob); + await expect(page.locator(".mx_MessageComposer_e2eIcon")).toMatchScreenshot("composer-e2e-icon-normal.png"); + await testMessages(page, bob, bobRoomId); await verify(app, bob); diff --git a/playwright/snapshots/crypto/crypto.spec.ts/composer-e2e-icon-normal-linux.png b/playwright/snapshots/crypto/crypto.spec.ts/composer-e2e-icon-normal-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..70a3795fc9c05c5d80e8d6ca898e3ac87efd0f20 GIT binary patch literal 268 zcmeAS@N?(olHy`uVBq!ia0vp^JRmj)6Oa`0mJkI}2R&UJLn`L%nRu3~iGk<1=@ply z{4Ps37;vku?3j08a_p+${+lbkOI}>DW|2L$Z=u4k14iTJ&nO#H=jIU+OGMzQONjubRbFXdo3m zjhEB&*lpjvYeeE>ul%<@Uis!5yT>M`_x2As85sWmmwP^AJJ2(1AkQ!}%za?E`ugYp QsX!41Pgg&ebxsLQ0BcWgbpQYW literal 0 HcmV?d00001 diff --git a/res/css/views/rooms/_E2EIcon.pcss b/res/css/views/rooms/_E2EIcon.pcss index aea1b942d1..024b6f637a 100644 --- a/res/css/views/rooms/_E2EIcon.pcss +++ b/res/css/views/rooms/_E2EIcon.pcss @@ -52,7 +52,13 @@ Please see LICENSE files in the repository root for full details. .mx_E2EIcon_normal::after { mask-image: url("$(res)/img/e2e/normal.svg"); - background-color: white; + background-color: var(--cpd-color-icon-tertiary); +} + +.mx_E2EIcon_verified { + .mx_E2EIcon_normal::after { + background-color: white; + } } .mx_E2EIcon_verified::after { From beaabd5b4440793547033f00c2015a0ed3868bd5 Mon Sep 17 00:00:00 2001 From: David Langley Date: Mon, 28 Jul 2025 15:21:24 +0100 Subject: [PATCH 05/14] bump wysiwyg to 2.39.0 (#30421) --- package.json | 2 +- yarn.lock | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index f0f1bd6620..5a33972fd1 100644 --- a/package.json +++ b/package.json @@ -99,7 +99,7 @@ "@types/react-virtualized": "^9.21.30", "@vector-im/compound-design-tokens": "^5.0.0", "@vector-im/compound-web": "^8.1.2", - "@vector-im/matrix-wysiwyg": "2.38.4", + "@vector-im/matrix-wysiwyg": "2.39.0", "@zxcvbn-ts/core": "^3.0.4", "@zxcvbn-ts/language-common": "^3.0.4", "@zxcvbn-ts/language-en": "^3.0.2", diff --git a/yarn.lock b/yarn.lock index 2e946741e6..bdac5418fc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4543,16 +4543,16 @@ classnames "^2.5.1" vaul "^1.0.0" -"@vector-im/matrix-wysiwyg-wasm@link:../../../../Library/Caches/Yarn/v6/npm-@vector-im-matrix-wysiwyg-2.38.4-fb0001dea01010a1e3ffc7042596e2d001ce9389-integrity/node_modules/bindings/wysiwyg-wasm": +"@vector-im/matrix-wysiwyg-wasm@link:../../bindings/wysiwyg-wasm": version "0.0.0" uid "" -"@vector-im/matrix-wysiwyg@2.38.4": - version "2.38.4" - resolved "https://registry.yarnpkg.com/@vector-im/matrix-wysiwyg/-/matrix-wysiwyg-2.38.4.tgz#fb0001dea01010a1e3ffc7042596e2d001ce9389" - integrity sha512-X6ky+1cf33SPdEVd6iTmOKfZZ2mDJv9cz3sHtDhuclS6uitK3QE8td/pmGqBj4ek2Ia4y0mnU61LfxvMry1SMA== +"@vector-im/matrix-wysiwyg@2.39.0": + version "2.39.0" + resolved "https://registry.yarnpkg.com/@vector-im/matrix-wysiwyg/-/matrix-wysiwyg-2.39.0.tgz#a6238e517f23a2f3025d9c65445914771c63b163" + integrity sha512-OROXnzPcQWrCMoUpIrCKEC4FYU+9SsRomUgu+VbJwWtBDkCbfvLD4z6w/mgiADw3iTUpBPgmcWJoGxesFuB20Q== dependencies: - "@vector-im/matrix-wysiwyg-wasm" "link:../../Library/Caches/Yarn/v6/npm-@vector-im-matrix-wysiwyg-2.38.4-fb0001dea01010a1e3ffc7042596e2d001ce9389-integrity/node_modules/bindings/wysiwyg-wasm" + "@vector-im/matrix-wysiwyg-wasm" "link:../../Library/Caches/Yarn/v6/npm-@vector-im-matrix-wysiwyg-2.39.0-a6238e517f23a2f3025d9c65445914771c63b163-integrity/node_modules/bindings/wysiwyg-wasm" "@vitest/expect@3.2.4": version "3.2.4" From 7e40e3697f25d561b2df1ce663b12590e9a98a01 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> Date: Mon, 28 Jul 2025 17:32:53 +0100 Subject: [PATCH 06/14] MatrixChat test robustness fixes (#30413) * MatrixChat-test: clean up better in `afterEach` Make the MatrixChat tests behave better by letting them finish their work in an `act` in afterEach. Otherwise we can end up mounting new components during cleanup, which run tasks in the background * MatrixChat-test: clean up dispatcher test This test was kicking off a dispatcher job which would then open a UserDeviceSettings dialog once the test had finished. That would then throw exceptions because some of the mock environment had been torn down. We're just testing that it opens the right dialog, so better to intercept `createDialog`. Aso add an `act` to reduce warnings, and replace a `flushPromises` with a `waitFor` to make the test more robust. --- .../components/structures/MatrixChat-test.tsx | 39 ++++++++++++------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/test/unit-tests/components/structures/MatrixChat-test.tsx b/test/unit-tests/components/structures/MatrixChat-test.tsx index c813143142..c00d26750c 100644 --- a/test/unit-tests/components/structures/MatrixChat-test.tsx +++ b/test/unit-tests/components/structures/MatrixChat-test.tsx @@ -71,6 +71,8 @@ import { SetupEncryptionStore } from "../../../../src/stores/SetupEncryptionStor import { ShareFormat } from "../../../../src/dispatcher/payloads/SharePayload.ts"; import { clearStorage } from "../../../../src/Lifecycle"; import RoomListStore from "../../../../src/stores/room-list/RoomListStore.ts"; +import UserSettingsDialog from "../../../../src/components/views/dialogs/UserSettingsDialog.tsx"; +import { SdkContextClass } from "../../../../src/contexts/SDKContext.ts"; jest.mock("matrix-js-sdk/src/oidc/authorize", () => ({ completeAuthorizationCodeGrant: jest.fn(), @@ -268,6 +270,10 @@ describe("", () => { // (must be sync otherwise the next test will start before it happens) act(() => defaultDispatcher.dispatch({ action: Action.OnLoggedOut }, true)); + // that will cause the Login to kick off an update in the background, which we need to allow to finish within + // an `act` to avoid warnings + await flushPromises(); + localStorage.clear(); }); @@ -640,22 +646,29 @@ describe("", () => { }); describe("onAction()", () => { - beforeEach(() => { - jest.spyOn(defaultDispatcher, "dispatch").mockClear(); - jest.spyOn(defaultDispatcher, "fire").mockClear(); + afterEach(() => { + jest.restoreAllMocks(); }); - it("should open user device settings", async () => { + + it("ViewUserDeviceSettings should open user device settings", async () => { await getComponentAndWaitForReady(); - defaultDispatcher.dispatch({ - action: Action.ViewUserDeviceSettings, - }); + const createDialog = jest.spyOn(Modal, "createDialog").mockReturnValue({} as any); - await flushPromises(); + await act(async () => { + defaultDispatcher.dispatch({ + action: Action.ViewUserDeviceSettings, + }); - expect(defaultDispatcher.dispatch).toHaveBeenCalledWith({ - action: Action.ViewUserSettings, - initialTabId: UserTab.SessionManager, + await waitFor(() => + expect(createDialog).toHaveBeenCalledWith( + UserSettingsDialog, + { initialTabId: UserTab.SessionManager, sdkContext: expect.any(SdkContextClass) }, + /*className=*/ undefined, + /*isPriority=*/ false, + /*isStatic=*/ true, + ), + ); }); }); @@ -674,10 +687,6 @@ describe("", () => { jest.spyOn(ReleaseAnnouncementStore.instance, "getReleaseAnnouncement").mockReturnValue(null); }); - afterEach(() => { - jest.restoreAllMocks(); - }); - describe("forget_room", () => { it("should dispatch after_forget_room action on successful forget", async () => { await clearAllModals(); From 45a2fd9d63421f4b6b8f34daf7cddc88c17b55e1 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> Date: Mon, 28 Jul 2025 22:07:20 +0100 Subject: [PATCH 07/14] Re-enable matrixchat test (#30410) Now that we have better logging for our tests (https://github.com/element-hq/element-web/pull/30405), I'd like to re-enable this test so we can try and understsnd what makes it fail. --- test/unit-tests/components/structures/MatrixChat-test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit-tests/components/structures/MatrixChat-test.tsx b/test/unit-tests/components/structures/MatrixChat-test.tsx index c00d26750c..6d8dcec1a7 100644 --- a/test/unit-tests/components/structures/MatrixChat-test.tsx +++ b/test/unit-tests/components/structures/MatrixChat-test.tsx @@ -1613,7 +1613,7 @@ describe("", () => { }); // Flaky test, see https://github.com/element-hq/element-web/issues/30337 - it.skip("waits for other tab to stop during startup", async () => { + it("waits for other tab to stop during startup", async () => { fetchMock.get("/welcome.html", { body: "

Hello

" }); jest.spyOn(Lifecycle, "attemptDelegatedAuthLogin"); From 9232a220dc5716cbf32f029ee6301c1d2e0d3f6e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 29 Jul 2025 11:15:11 +0100 Subject: [PATCH 08/14] Update dependency filesize to v11 (#30380) * Update dependency filesize to v11 * Update fileSize types Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Michael Telatynski <7t3chguy@gmail.com> --- package.json | 2 +- src/utils/FileUtils.ts | 36 ++++++------------------------------ yarn.lock | 8 ++++---- 3 files changed, 11 insertions(+), 35 deletions(-) diff --git a/package.json b/package.json index 5a33972fd1..49d03f0821 100644 --- a/package.json +++ b/package.json @@ -117,7 +117,7 @@ "emojibase-regex": "15.3.2", "escape-html": "^1.0.3", "file-saver": "^2.0.5", - "filesize": "10.1.6", + "filesize": "11.0.2", "github-markdown-css": "^5.5.1", "glob-to-regexp": "^0.4.1", "highlight.js": "^11.3.1", diff --git a/src/utils/FileUtils.ts b/src/utils/FileUtils.ts index 1240dc61db..7958489057 100644 --- a/src/utils/FileUtils.ts +++ b/src/utils/FileUtils.ts @@ -7,16 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com Please see LICENSE files in the repository root for full details. */ -import { - filesize, - type FileSizeOptionsArray, - type FileSizeOptionsBase, - type FileSizeOptionsExponent, - type FileSizeOptionsObject, - type FileSizeOptionsString, - type FileSizeReturnArray, - type FileSizeReturnObject, -} from "filesize"; +import { filesize, type FilesizeOptions, type FilesizeReturn } from "filesize"; import { type MediaEventContent } from "matrix-js-sdk/src/types"; import { _t } from "../languageHandler"; @@ -27,7 +18,7 @@ export function downloadLabelForFile(content: MediaEventContent, withSize = true if (content.info?.size && withSize) { // If we know the size of the file then add it as human-readable string to the end of the link text // so that the user knows how big a file they are downloading. - text += " (" + fileSize(content.info.size, { base: 2, standard: "jedec" }) + ")"; + text += " (" + fileSize(content.info.size, { base: 2, standard: "jedec" }) + ")"; } return text; } @@ -83,18 +74,11 @@ export function presentableTextForFile( // it since it is "ugly", users generally aren't aware what it // means and the type of the attachment can usually be inferred // from the file extension. - text += " (" + fileSize(content.info.size, { base: 2, standard: "jedec" }) + ")"; + text += " (" + fileSize(content.info.size, { base: 2, standard: "jedec" }) + ")"; } return text; } -type FileSizeOptions = - | FileSizeOptionsString - | FileSizeOptionsBase - | FileSizeOptionsArray - | FileSizeOptionsExponent - | FileSizeOptionsObject; - /** * wrapper function to set default values for filesize function * @@ -106,15 +90,7 @@ type FileSizeOptions = * exponent: number; * unit: string;}} formatted file size with unit e.g. 12kB, 12KB */ -export function fileSize(byteCount: number, options: FileSizeOptionsString | FileSizeOptionsBase): string; -export function fileSize(byteCount: number, options: FileSizeOptionsArray): FileSizeReturnArray; -export function fileSize(byteCount: number, options: FileSizeOptionsExponent): number; -export function fileSize(byteCount: number, options: FileSizeOptionsObject): FileSizeReturnObject; -export function fileSize(byteCount: number): string; -export function fileSize( - byteCount: number, - options?: FileSizeOptions, -): string | number | FileSizeReturnArray | FileSizeReturnObject { - const defaultOption: FileSizeOptions = { base: 2, standard: "jedec", ...options }; - return filesize(byteCount, defaultOption); +export function fileSize(byteCount: number, options?: O): FilesizeReturn { + const defaultOption = { base: 2, standard: "jedec", ...options } as O; + return filesize(byteCount, defaultOption); } diff --git a/yarn.lock b/yarn.lock index bdac5418fc..5d47ac3811 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8108,10 +8108,10 @@ filelist@^1.0.4: dependencies: minimatch "^5.0.1" -filesize@10.1.6: - version "10.1.6" - resolved "https://registry.yarnpkg.com/filesize/-/filesize-10.1.6.tgz#31194da825ac58689c0bce3948f33ce83aabd361" - integrity sha512-sJslQKU2uM33qH5nqewAwVB2QgR6w1aMNsYUp3aN5rMRyXEwJGmZvaWzeJFNTOXWlHQyBFCWrdj3fV/fsTOX8w== +filesize@11.0.2: + version "11.0.2" + resolved "https://registry.yarnpkg.com/filesize/-/filesize-11.0.2.tgz#b7771e3836812582ad74b8a10d6eb0dc58c1ceda" + integrity sha512-s/iAeeWLk5BschUIpmdrF8RA8lhFZ/xDZgKw1Tan72oGws1/dFGB06nYEiyyssWUfjKNQTNRlrwMVjO9/hvXDw== fill-range@^7.1.1: version "7.1.1" From d1f62317bab69ee3b8a35eff17684d2875edc360 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Tue, 29 Jul 2025 13:01:13 +0000 Subject: [PATCH 09/14] Upgrade dependency to matrix-js-sdk@37.12.0 --- package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 5de87a38df..ffdc644398 100644 --- a/package.json +++ b/package.json @@ -134,7 +134,7 @@ "maplibre-gl": "^5.0.0", "matrix-encrypt-attachment": "^1.0.3", "matrix-events-sdk": "0.0.1", - "matrix-js-sdk": "37.12.0-rc.0", + "matrix-js-sdk": "37.12.0", "matrix-widget-api": "^1.10.0", "memoize-one": "^6.0.0", "mime": "^4.0.4", diff --git a/yarn.lock b/yarn.lock index 579fb24dff..302c688927 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4549,7 +4549,7 @@ classnames "^2.5.1" vaul "^1.0.0" -"@vector-im/matrix-wysiwyg-wasm@link:../../../../Library/Caches/Yarn/v6/npm-@vector-im-matrix-wysiwyg-2.38.4-fb0001dea01010a1e3ffc7042596e2d001ce9389-integrity/node_modules/bindings/wysiwyg-wasm": +"@vector-im/matrix-wysiwyg-wasm@link:../../../.cache/yarn/v6/npm-@vector-im-matrix-wysiwyg-2.38.4-fb0001dea01010a1e3ffc7042596e2d001ce9389-integrity/node_modules/bindings/wysiwyg-wasm": version "0.0.0" uid "" @@ -10827,10 +10827,10 @@ matrix-events-sdk@0.0.1: resolved "https://registry.yarnpkg.com/matrix-events-sdk/-/matrix-events-sdk-0.0.1.tgz#c8c38911e2cb29023b0bbac8d6f32e0de2c957dd" integrity sha512-1QEOsXO+bhyCroIe2/A5OwaxHvBm7EsSQ46DEDn8RBIfQwN5HWBpFvyWWR4QY0KHPPnnJdI99wgRiAl7Ad5qaA== -matrix-js-sdk@37.12.0-rc.0: - version "37.12.0-rc.0" - resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-37.12.0-rc.0.tgz#8c439319298a4a74999c9f1cc1222d2799d0f718" - integrity sha512-HFghuEEBgV/ljs34w/Nyqc/E7i1yddopkJdxp6EuerZEeDcJVMi6PbApzLBmbGiRReVzeplmP6yb71g90kTSWw== +matrix-js-sdk@37.12.0: + version "37.12.0" + resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-37.12.0.tgz#720d8b676e82ee809b227e667ce5fdd63aa8c099" + integrity sha512-2JSTMtvACE4egrBPp0ZQ7fSxBXcX6xuHcQSjcoBiBxFL7W0SZCl4qsNl30pBshDTe5wARAByzIHEMv6bGVKKNA== dependencies: "@babel/runtime" "^7.12.5" "@matrix-org/matrix-sdk-crypto-wasm" "^15.0.0" From 5a4b5418cce5fff99b32654e92b5eee496d7b48a Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Tue, 29 Jul 2025 13:04:43 +0000 Subject: [PATCH 10/14] v1.11.107 --- CHANGELOG.md | 19 +++++++++++++++++++ package.json | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b7f3c4febd..e578d777f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,22 @@ +Changes in [1.11.107](https://github.com/element-hq/element-web/releases/tag/v1.11.107) (2025-07-29) +==================================================================================================== +## ✨ Features + +* Message preview should show tooltip with the full message on hover ([#30265](https://github.com/element-hq/element-web/pull/30265)). Contributed by @MidhunSureshR. +* Support rendering notification badges on platforms that do their own icon overlays ([#30315](https://github.com/element-hq/element-web/pull/30315)). Contributed by @Half-Shot. +* Add SubscriptionViewModel base class ([#30297](https://github.com/element-hq/element-web/pull/30297)). Contributed by @dbkr. +* Enhancement: Save image on CTRL+S ([#30330](https://github.com/element-hq/element-web/pull/30330)). Contributed by @ioalexander. +* Add quote functionality to MessageContextMenu (#29893) ([#30323](https://github.com/element-hq/element-web/pull/30323)). Contributed by @AlirezaMrtz. +* Initial structure for shared component views ([#30216](https://github.com/element-hq/element-web/pull/30216)). Contributed by @dbkr. + +## 🐛 Bug Fixes + +* [Backport staging] Fix e2e shield being invisible in white mode for encrypted room ([#30411](https://github.com/element-hq/element-web/pull/30411)). Contributed by @RiotRobot. +* Force ED titlebar color for new room list ([#30332](https://github.com/element-hq/element-web/pull/30332)). Contributed by @florianduros. +* Add a background color to left panel for macos titlebar in element desktop ([#30328](https://github.com/element-hq/element-web/pull/30328)). Contributed by @florianduros. +* Fix: Prevent page refresh on Enter key in right panel member search ([#30312](https://github.com/element-hq/element-web/pull/30312)). Contributed by @AlirezaMrtz. + + Changes in [1.11.106](https://github.com/element-hq/element-web/releases/tag/v1.11.106) (2025-07-15) ==================================================================================================== ## ✨ Features diff --git a/package.json b/package.json index ffdc644398..2361007e77 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "element-web", - "version": "1.11.107-rc.0", + "version": "1.11.107", "description": "Element: the future of secure communication", "author": "New Vector Ltd.", "repository": { From 94aa51dc5799bf97a7a991add984dcdff424c62b Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Tue, 29 Jul 2025 13:08:36 +0000 Subject: [PATCH 11/14] Reset matrix-js-sdk back to develop branch --- package.json | 2 +- yarn.lock | 19 +++++++++---------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index d9e6084893..0172f3e0b5 100644 --- a/package.json +++ b/package.json @@ -135,7 +135,7 @@ "maplibre-gl": "^5.0.0", "matrix-encrypt-attachment": "^1.0.3", "matrix-events-sdk": "0.0.1", - "matrix-js-sdk": "37.12.0", + "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop", "matrix-widget-api": "^1.10.0", "memoize-one": "^6.0.0", "mime": "^4.0.4", diff --git a/yarn.lock b/yarn.lock index 5c2086bfb6..3ac17bbbe1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2463,10 +2463,10 @@ emojibase "^15.3.1" emojibase-data "^15.3.1" -"@matrix-org/matrix-sdk-crypto-wasm@^15.0.0": - version "15.0.0" - resolved "https://registry.yarnpkg.com/@matrix-org/matrix-sdk-crypto-wasm/-/matrix-sdk-crypto-wasm-15.0.0.tgz#5b29ca1c62f3aface9db06d7441d0a9ba2cd3439" - integrity sha512-tzBGf/jugrOw190Na77LljZIQMTSL6SAnZaATKMlb2j1XOfc5Q+bSJTb9ZWBR7TFs0d8K9spcwRHPc4S/7CMYw== +"@matrix-org/matrix-sdk-crypto-wasm@^15.1.0": + version "15.1.0" + resolved "https://registry.yarnpkg.com/@matrix-org/matrix-sdk-crypto-wasm/-/matrix-sdk-crypto-wasm-15.1.0.tgz#653956f5f6daced55a9df3d2c1114eb2c017b528" + integrity sha512-ZsDdjn46J3+VxsDLmaSODuS+qtGZB/i3Cg9tWL1QPNjvAWzNaTHQ7glleByI2PKVBm83aklfuhGKT2MqE1ZsEA== "@matrix-org/react-sdk-module-api@^2.4.0": version "2.5.0" @@ -4543,7 +4543,7 @@ classnames "^2.5.1" vaul "^1.0.0" -"@vector-im/matrix-wysiwyg-wasm@link:../../bindings/wysiwyg-wasm": +"@vector-im/matrix-wysiwyg-wasm@link:../../Library/Caches/Yarn/v6/npm-@vector-im-matrix-wysiwyg-2.39.0-a6238e517f23a2f3025d9c65445914771c63b163-integrity/node_modules/bindings/wysiwyg-wasm": version "0.0.0" uid "" @@ -4552,7 +4552,7 @@ resolved "https://registry.yarnpkg.com/@vector-im/matrix-wysiwyg/-/matrix-wysiwyg-2.39.0.tgz#a6238e517f23a2f3025d9c65445914771c63b163" integrity sha512-OROXnzPcQWrCMoUpIrCKEC4FYU+9SsRomUgu+VbJwWtBDkCbfvLD4z6w/mgiADw3iTUpBPgmcWJoGxesFuB20Q== dependencies: - "@vector-im/matrix-wysiwyg-wasm" "link:../../Library/Caches/Yarn/v6/npm-@vector-im-matrix-wysiwyg-2.39.0-a6238e517f23a2f3025d9c65445914771c63b163-integrity/node_modules/bindings/wysiwyg-wasm" + "@vector-im/matrix-wysiwyg-wasm" "link:../../../.cache/yarn/v6/npm-@vector-im-matrix-wysiwyg-2.39.0-a6238e517f23a2f3025d9c65445914771c63b163-integrity/node_modules/bindings/wysiwyg-wasm" "@vitest/expect@3.2.4": version "3.2.4" @@ -10845,13 +10845,12 @@ matrix-events-sdk@0.0.1: resolved "https://registry.yarnpkg.com/matrix-events-sdk/-/matrix-events-sdk-0.0.1.tgz#c8c38911e2cb29023b0bbac8d6f32e0de2c957dd" integrity sha512-1QEOsXO+bhyCroIe2/A5OwaxHvBm7EsSQ46DEDn8RBIfQwN5HWBpFvyWWR4QY0KHPPnnJdI99wgRiAl7Ad5qaA== -matrix-js-sdk@37.12.0: +"matrix-js-sdk@github:matrix-org/matrix-js-sdk#develop": version "37.12.0" - resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-37.12.0.tgz#720d8b676e82ee809b227e667ce5fdd63aa8c099" - integrity sha512-2JSTMtvACE4egrBPp0ZQ7fSxBXcX6xuHcQSjcoBiBxFL7W0SZCl4qsNl30pBshDTe5wARAByzIHEMv6bGVKKNA== + resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/56b24c0bdc3e1c6b9778dffa5cab7959848f4e0e" dependencies: "@babel/runtime" "^7.12.5" - "@matrix-org/matrix-sdk-crypto-wasm" "^15.0.0" + "@matrix-org/matrix-sdk-crypto-wasm" "^15.1.0" another-json "^0.2.0" bs58 "^6.0.0" content-type "^1.0.4" From ee120f2fa9cee5b362becb8253f3a2d63f2db3d8 Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Tue, 29 Jul 2025 18:40:56 +0100 Subject: [PATCH 12/14] Use server name explicitly for via. (#30362) * Use server name explicitly for via. * lint --- playwright/e2e/spaces/spaces.spec.ts | 29 +++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/playwright/e2e/spaces/spaces.spec.ts b/playwright/e2e/spaces/spaces.spec.ts index 56c8ae22b8..b3f7ecb0c9 100644 --- a/playwright/e2e/spaces/spaces.spec.ts +++ b/playwright/e2e/spaces/spaces.spec.ts @@ -23,7 +23,7 @@ async function openSpaceContextMenu(page: Page, app: ElementAppPage, spaceName: return page.locator(".mx_SpacePanel_contextMenu"); } -function spaceCreateOptions(spaceName: string, roomIds: string[] = []): ICreateRoomOpts { +function spaceCreateOptions(serverName: string, spaceName: string, roomIds: string[] = []): ICreateRoomOpts { return { creation_content: { type: "m.space", @@ -35,17 +35,21 @@ function spaceCreateOptions(spaceName: string, roomIds: string[] = []): ICreateR name: spaceName, }, }, - ...roomIds.map((r) => spaceChildInitialState(r)), + ...roomIds.map((r) => spaceChildInitialState(serverName, r)), ], }; } -function spaceChildInitialState(roomId: string, order?: string): ICreateRoomOpts["initial_state"]["0"] { +function spaceChildInitialState( + serverName: string, + roomId: string, + order?: string, +): ICreateRoomOpts["initial_state"]["0"] { return { type: "m.space.child", state_key: roomId, content: { - via: [roomId.split(":")[1]], + via: [serverName], order, }, }; @@ -240,7 +244,7 @@ test.describe("Spaces", () => { }); await expect(await app.getSpacePanelButton("My Space")).toBeVisible(); - const roomId = await bot.createRoom(spaceCreateOptions("Space Space")); + const roomId = await bot.createRoom(spaceCreateOptions(user.homeServer, "Space Space")); await bot.inviteUser(roomId, user.userId); // Assert that `Space Space` is above `My Space` due to it being an invite @@ -260,7 +264,10 @@ test.describe("Spaces", () => { const spaceName = "Spacey Mc. Space Space"; await app.client.createSpace({ name: spaceName, - initial_state: [spaceChildInitialState(roomId1), spaceChildInitialState(roomId2)], + initial_state: [ + spaceChildInitialState(user.homeServer, roomId1), + spaceChildInitialState(user.homeServer, roomId2), + ], }); await app.viewSpaceHomeByName(spaceName); @@ -287,7 +294,7 @@ test.describe("Spaces", () => { }); await app.client.createSpace({ name: "Root Space", - initial_state: [spaceChildInitialState(childSpaceId)], + initial_state: [spaceChildInitialState(user.homeServer, childSpaceId)], }); // Find collapsed Space panel @@ -323,7 +330,7 @@ test.describe("Spaces", () => { name: "Test Room", topic: "This is a topic https://github.com/matrix-org/matrix-react-sdk/pull/10060 with a link", }); - const spaceId = await bot.createRoom(spaceCreateOptions("Test Space", [roomId])); + const spaceId = await bot.createRoom(spaceCreateOptions(user.homeServer, "Test Space", [roomId])); await bot.inviteUser(spaceId, user.userId); await expect(await app.getSpacePanelButton("Test Space")).toBeVisible(); @@ -361,9 +368,9 @@ test.describe("Spaces", () => { await app.client.createSpace({ name: "Root Space", initial_state: [ - spaceChildInitialState(childSpaceId1, "a"), - spaceChildInitialState(childSpaceId2, "b"), - spaceChildInitialState(childSpaceId3, "c"), + spaceChildInitialState(user.homeServer, childSpaceId1, "a"), + spaceChildInitialState(user.homeServer, childSpaceId2, "b"), + spaceChildInitialState(user.homeServer, childSpaceId3, "c"), ], }); await app.viewSpaceByName("Root Space"); From 452996eacf231a46a2ebd109caaf9a82df7f4bc3 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> Date: Wed, 30 Jul 2025 13:11:14 +0100 Subject: [PATCH 13/14] Playwright: clean up after verification test, to deflake later tests (#30425) --- playwright/e2e/crypto/device-verification.spec.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/playwright/e2e/crypto/device-verification.spec.ts b/playwright/e2e/crypto/device-verification.spec.ts index f325754326..eb21dfc909 100644 --- a/playwright/e2e/crypto/device-verification.spec.ts +++ b/playwright/e2e/crypto/device-verification.spec.ts @@ -124,6 +124,10 @@ test.describe("Device verification", { tag: "@no-webkit" }, () => { const toasts = new Toasts(page); await toasts.rejectToast("Notifications"); await toasts.assertNoToasts(); + + // There may still be a `/sendToDevice/m.secret.request` in flight, which will later throw an error and cause + // a *subsequent* test to fail. Tell playwright to ignore any errors resulting from in-flight routes. + await page.unrouteAll({ behavior: "ignoreErrors" }); }); test("Verify device with QR code during login", async ({ page, app, credentials, homeserver }) => { From 1e15a322a53b135c909b9f8e9c26b9497dc0f0a9 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 30 Jul 2025 13:30:18 +0100 Subject: [PATCH 14/14] Fix downloaded attachments not being decrypted (#30433) * Fix downloaded attachments not being decrypted Fixes https://github.com/element-hq/element-web/issues/30339 * Import order --- src/hooks/useDownloadMedia.ts | 18 ++++++---- .../views/elements/ImageView-test.tsx | 35 +++++++++++++++++++ 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/src/hooks/useDownloadMedia.ts b/src/hooks/useDownloadMedia.ts index 74328ac7ca..eb0af954e0 100644 --- a/src/hooks/useDownloadMedia.ts +++ b/src/hooks/useDownloadMedia.ts @@ -59,15 +59,19 @@ export function useDownloadMedia(url: string, fileName?: string, mxEvent?: Matri return downloadBlob(blobRef.current); } - const res = await fetch(url); - if (!res.ok) { - throw parseErrorResponse(res, await res.text()); + // We must download via the mediaEventHelper if given as the file may need decryption. + if (mediaEventHelper) { + blobRef.current = await mediaEventHelper.sourceBlob.value; + } else { + const res = await fetch(url); + if (!res.ok) { + throw parseErrorResponse(res, await res.text()); + } + + blobRef.current = await res.blob(); } - const blob = await res.blob(); - blobRef.current = blob; - - await downloadBlob(blob); + await downloadBlob(blobRef.current); } catch (e) { showError(e); } diff --git a/test/unit-tests/components/views/elements/ImageView-test.tsx b/test/unit-tests/components/views/elements/ImageView-test.tsx index b0e9338f69..6537a3948a 100644 --- a/test/unit-tests/components/views/elements/ImageView-test.tsx +++ b/test/unit-tests/components/views/elements/ImageView-test.tsx @@ -10,11 +10,13 @@ import React from "react"; import { mocked } from "jest-mock"; import { render, fireEvent, waitFor } from "jest-matrix-react"; import fetchMock from "fetch-mock-jest"; +import { MatrixEvent } from "matrix-js-sdk/src/matrix"; import ImageView from "../../../../../src/components/views/elements/ImageView"; import { FileDownloader } from "../../../../../src/utils/FileDownloader"; import Modal from "../../../../../src/Modal"; import ErrorDialog from "../../../../../src/components/views/dialogs/ErrorDialog"; +import { stubClient } from "../../../../test-utils"; jest.mock("../../../../../src/utils/FileDownloader"); @@ -44,6 +46,39 @@ describe("", () => { expect(fetchMock).toHaveFetched("https://example.com/image.png"); }); + it("should use event as download source if given", async () => { + stubClient(); + + const event = new MatrixEvent({ + event_id: "$eventId", + type: "m.image", + content: { + body: "fromEvent.png", + url: "mxc://test.dummy/fromEvent.png", + file_name: "filename.png", + }, + origin_server_ts: new Date(2000, 0, 1, 0, 0, 0, 0).getTime(), + }); + + fetchMock.get("http://this.is.a.url/test.dummy/fromEvent.png", "TESTFILE"); + const { getByRole } = render( + , + ); + fireEvent.click(getByRole("button", { name: "Download" })); + await waitFor(() => + expect(mocked(FileDownloader).mock.instances[0].download).toHaveBeenCalledWith({ + blob: expect.anything(), + name: "fromEvent.png", + }), + ); + expect(fetchMock).toHaveFetched("http://this.is.a.url/test.dummy/fromEvent.png"); + }); + it("should start download on Ctrl+S", async () => { fetchMock.get("https://example.com/image.png", "TESTFILE");