From 3c87309f7d6ef62fb65a7a4a43fcccec484612f8 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Tue, 17 Mar 2026 11:41:10 +0000 Subject: [PATCH 1/5] Upgrade dependency to matrix-js-sdk@41.2.0-rc.0 --- apps/web/package.json | 2 +- pnpm-lock.yaml | 11 +++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/apps/web/package.json b/apps/web/package.json index 94a490288d..1ece9bea9f 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -81,7 +81,7 @@ "lodash": "npm:lodash-es@^4.17.21", "maplibre-gl": "^5.0.0", "matrix-encrypt-attachment": "^1.0.3", - "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop", + "matrix-js-sdk": "41.2.0-rc.0", "matrix-widget-api": "^1.16.1", "memoize-one": "^6.0.0", "mime": "^4.0.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d71dc00771..972fe75823 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -277,8 +277,8 @@ importers: specifier: ^1.0.3 version: 1.0.3 matrix-js-sdk: - specifier: github:matrix-org/matrix-js-sdk#develop - version: https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/d99363d288b8471e38892ec11fd9b37c062b85fe + specifier: 41.2.0-rc.0 + version: 41.2.0-rc.0 matrix-widget-api: specifier: ^1.17.0 version: 1.17.0 @@ -7819,9 +7819,8 @@ packages: matrix-events-sdk@0.0.1: resolution: {integrity: sha512-1QEOsXO+bhyCroIe2/A5OwaxHvBm7EsSQ46DEDn8RBIfQwN5HWBpFvyWWR4QY0KHPPnnJdI99wgRiAl7Ad5qaA==} - matrix-js-sdk@https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/d99363d288b8471e38892ec11fd9b37c062b85fe: - resolution: {tarball: https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/d99363d288b8471e38892ec11fd9b37c062b85fe} - version: 41.1.0 + matrix-js-sdk@41.2.0-rc.0: + resolution: {integrity: sha512-5XGdv7vvkmSjTVMAPHCRF7p5RJR8MH+hFpdV3PRIe6UliIROEUnVjetG24/PF6ksg10obGhBBo3dsLZw1dhHPQ==} engines: {node: '>=22.0.0'} matrix-web-i18n@3.6.0: @@ -18712,7 +18711,7 @@ snapshots: matrix-events-sdk@0.0.1: {} - matrix-js-sdk@https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/d99363d288b8471e38892ec11fd9b37c062b85fe: + matrix-js-sdk@41.2.0-rc.0: dependencies: '@babel/runtime': 7.28.6 '@matrix-org/matrix-sdk-crypto-wasm': 18.0.0 From 7b396e8de71379cc65b54844d1cca93640b82633 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Tue, 17 Mar 2026 11:43:46 +0000 Subject: [PATCH 2/5] v1.12.13-rc.0 --- apps/web/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/web/package.json b/apps/web/package.json index 1ece9bea9f..2f3cca6d09 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -1,6 +1,6 @@ { "name": "element-web", - "version": "1.12.12", + "version": "1.12.13-rc.0", "description": "Element: the future of secure communication", "author": "New Vector Ltd.", "repository": { From 09f56ed3b6d45b620fade8130c672c54ab669d00 Mon Sep 17 00:00:00 2001 From: ElementRobot Date: Fri, 20 Mar 2026 16:44:40 +0100 Subject: [PATCH 3/5] [Backport staging] Fix soft crash of room list when trying to open a room (#32872) * Fix soft crash of room list when trying to open a room (#32864) * fix: soft crash of room list trying to get item vm * test: add test to check roomMap recovery and cleared when needed (cherry picked from commit 9358096ac6ebf1fed4b6097658bc75b21c8fc366) * test: fix room list vm usage in test https://github.com/element-hq/element-web/pull/32819 has renamed the vm but this PR isn't in the base branch of the backport --------- Co-authored-by: Florian Duros Co-authored-by: Florian Duros --- .../room-list/RoomListViewViewModel.ts | 23 +++++-- .../room-list/RoomListViewViewModel-test.tsx | 62 +++++++++++++++++++ 2 files changed, 79 insertions(+), 6 deletions(-) diff --git a/apps/web/src/viewmodels/room-list/RoomListViewViewModel.ts b/apps/web/src/viewmodels/room-list/RoomListViewViewModel.ts index 2eaea3d246..3f241c584f 100644 --- a/apps/web/src/viewmodels/room-list/RoomListViewViewModel.ts +++ b/apps/web/src/viewmodels/room-list/RoomListViewViewModel.ts @@ -52,6 +52,9 @@ export class RoomListViewViewModel // Child view model management private roomItemViewModels = new Map(); + // This map is intentionally additive (never cleared except on space changes) to avoid a race condition: + // a list update can refresh roomsResult and roomsMap before the view re-renders, so the view may still + // request a view model for a room that was removed from the latest list. Keeping old entries prevents a crash. private roomsMap = new Map(); public constructor(props: RoomListViewViewModelProps) { @@ -142,11 +145,11 @@ export class RoomListViewViewModel }; /** - * Rebuild roomsMap when roomsResult changes. + * Add rooms from the RoomsResult to the roomsMap for quick lookup. + * This does not clear the roomsMap. * This maintains a quick lookup for room objects. */ private updateRoomsMap(roomsResult: RoomsResult): void { - this.roomsMap.clear(); for (const room of roomsResult.rooms) { this.roomsMap.set(room.roomId, room); } @@ -181,11 +184,15 @@ export class RoomListViewViewModel let viewModel = this.roomItemViewModels.get(roomId); if (!viewModel) { - const room = this.roomsMap.get(roomId); + let room = this.roomsMap.get(roomId); if (!room) { - throw new Error(`Room ${roomId} not found in roomsMap`); + // Maybe the roomsMap is out of date due to a recent roomsResult change that hasn't been applied yet (race condition) + this.updateRoomsMap(this.roomsResult); + room = this.roomsMap.get(roomId); } + if (!room) throw new Error(`Room ${roomId} not found in roomsMap`); + // Create new view model viewModel = new RoomListItemViewModel({ room, @@ -298,8 +305,6 @@ export class RoomListViewViewModel // Refresh room data from store this.roomsResult = RoomListStoreV3.instance.getSortedRoomsInActiveSpace(filterKeys); - this.updateRoomsMap(this.roomsResult); - const newSpaceId = this.roomsResult.spaceId; // Detect space change @@ -308,6 +313,10 @@ export class RoomListViewViewModel // We only want to do this on space changes, not on regular list updates, to preserve view models when possible // The view models are disposed when scrolling out of view (handled by updateVisibleRooms) this.clearViewModels(); + // Clear roomsMap to prevent stale room data - it will be repopulated with the new roomsResult + this.roomsMap.clear(); + + this.updateRoomsMap(this.roomsResult); // Space changed - get the last selected room for the new space to prevent flicker const lastSelectedRoom = SpaceStore.instance.getLastSelectedRoomIdForSpace(newSpaceId); @@ -316,6 +325,8 @@ export class RoomListViewViewModel return; } + this.updateRoomsMap(this.roomsResult); + // Normal room list update (not a space change) this.updateRoomListData(); }; diff --git a/apps/web/test/viewmodels/room-list/RoomListViewViewModel-test.tsx b/apps/web/test/viewmodels/room-list/RoomListViewViewModel-test.tsx index ceeb940669..4aaa370122 100644 --- a/apps/web/test/viewmodels/room-list/RoomListViewViewModel-test.tsx +++ b/apps/web/test/viewmodels/room-list/RoomListViewViewModel-test.tsx @@ -180,6 +180,25 @@ describe("RoomListViewViewModel", () => { expect(disposeSpy1).toHaveBeenCalled(); expect(disposeSpy2).toHaveBeenCalled(); }); + + it("should clear roomsMap when space changes and repopulate with new rooms", () => { + viewModel = new RoomListViewViewModel({ client: matrixClient }); + + const newSpaceRoom = mkStubRoom("!spaceroom:server", "Space Room", matrixClient); + + jest.spyOn(RoomListStoreV3.instance, "getSortedRoomsInActiveSpace").mockReturnValue({ + spaceId: "!space:server", + rooms: [newSpaceRoom], + }); + jest.spyOn(SpaceStore.instance, "getLastSelectedRoomIdForSpace").mockReturnValue(null); + + RoomListStoreV3.instance.emit(RoomListStoreV3Event.ListsUpdate); + + // New space room should be accessible + expect(() => viewModel.getRoomItemViewModel("!spaceroom:server")).not.toThrow(); + // Old rooms from the home space should not be accessible + expect(() => viewModel.getRoomItemViewModel("!room1:server")).toThrow(); + }); }); describe("Active room tracking", () => { @@ -342,6 +361,49 @@ describe("RoomListViewViewModel", () => { }).toThrow(); }); + it("should not throw when requesting view model for a room removed from the list but still in roomsMap", () => { + viewModel = new RoomListViewViewModel({ client: matrixClient }); + + // Normal list update removes room2 from the list + jest.spyOn(RoomListStoreV3.instance, "getSortedRoomsInActiveSpace").mockReturnValue({ + spaceId: "home", + rooms: [room1, room3], + }); + + RoomListStoreV3.instance.emit(RoomListStoreV3Event.ListsUpdate); + + expect(() => viewModel.getRoomItemViewModel("!room2:server")).not.toThrow(); + }); + + it("should throw when requesting view model for a room from old space after space change", () => { + viewModel = new RoomListViewViewModel({ client: matrixClient }); + + const spaceRoom = mkStubRoom("!newroom:server", "New Room", matrixClient); + + // Space change: new space only has spaceRoom + jest.spyOn(RoomListStoreV3.instance, "getSortedRoomsInActiveSpace").mockReturnValue({ + spaceId: "!space:server", + rooms: [spaceRoom], + }); + jest.spyOn(SpaceStore.instance, "getLastSelectedRoomIdForSpace").mockReturnValue(null); + + RoomListStoreV3.instance.emit(RoomListStoreV3Event.ListsUpdate); + + expect(() => viewModel.getRoomItemViewModel("!room1:server")).toThrow( + "Room !room1:server not found in roomsMap", + ); + }); + + it("should recover when roomsMap is stale but roomsResult has the room", () => { + viewModel = new RoomListViewViewModel({ client: matrixClient }); + + // Manually clear roomsMap to simulate stale cache, but keep roomsResult intact + (viewModel as any).roomsMap.clear(); + + // getRoomItemViewModel should retry by re-populating roomsMap from roomsResult + expect(() => viewModel.getRoomItemViewModel("!room1:server")).not.toThrow(); + }); + it("should dispose view models for rooms no longer visible", () => { viewModel = new RoomListViewViewModel({ client: matrixClient }); From b49a29f3df0bcac17667fa3ed1b5e9651b90f6b0 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Tue, 24 Mar 2026 11:23:51 +0000 Subject: [PATCH 4/5] Upgrade dependency to matrix-js-sdk@41.2.0 --- apps/web/package.json | 2 +- pnpm-lock.yaml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/web/package.json b/apps/web/package.json index 2f3cca6d09..e849ee1b93 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -81,7 +81,7 @@ "lodash": "npm:lodash-es@^4.17.21", "maplibre-gl": "^5.0.0", "matrix-encrypt-attachment": "^1.0.3", - "matrix-js-sdk": "41.2.0-rc.0", + "matrix-js-sdk": "41.2.0", "matrix-widget-api": "^1.16.1", "memoize-one": "^6.0.0", "mime": "^4.0.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 972fe75823..7f5c1ba770 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -277,8 +277,8 @@ importers: specifier: ^1.0.3 version: 1.0.3 matrix-js-sdk: - specifier: 41.2.0-rc.0 - version: 41.2.0-rc.0 + specifier: 41.2.0 + version: 41.2.0 matrix-widget-api: specifier: ^1.17.0 version: 1.17.0 @@ -7819,8 +7819,8 @@ packages: matrix-events-sdk@0.0.1: resolution: {integrity: sha512-1QEOsXO+bhyCroIe2/A5OwaxHvBm7EsSQ46DEDn8RBIfQwN5HWBpFvyWWR4QY0KHPPnnJdI99wgRiAl7Ad5qaA==} - matrix-js-sdk@41.2.0-rc.0: - resolution: {integrity: sha512-5XGdv7vvkmSjTVMAPHCRF7p5RJR8MH+hFpdV3PRIe6UliIROEUnVjetG24/PF6ksg10obGhBBo3dsLZw1dhHPQ==} + matrix-js-sdk@41.2.0: + resolution: {integrity: sha512-kVLDKm/bUlwlHoDKRemshs27LCnOnNpmsVKtbCOM5F5D/E1SkrKldou+vQ/lk4PyXTvu9/qglkd2m0pBwJ5opg==} engines: {node: '>=22.0.0'} matrix-web-i18n@3.6.0: @@ -18711,7 +18711,7 @@ snapshots: matrix-events-sdk@0.0.1: {} - matrix-js-sdk@41.2.0-rc.0: + matrix-js-sdk@41.2.0: dependencies: '@babel/runtime': 7.28.6 '@matrix-org/matrix-sdk-crypto-wasm': 18.0.0 From f72e09173b5279a99fc58eb4e673077faafca78a Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Tue, 24 Mar 2026 11:26:49 +0000 Subject: [PATCH 5/5] v1.12.13 --- CHANGELOG.md | 31 +++++++++++++++++++++++++++++++ apps/web/package.json | 2 +- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 94be73bcf5..78659f2037 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,34 @@ +Changes in [1.12.13](https://github.com/element-hq/element-web/releases/tag/v1.12.13) (2026-03-24) +================================================================================================== +## 🦖 Deprecations + +* Remove automatic rageshakes on UTD labs feature ([#32778](https://github.com/element-hq/element-web/pull/32778)). Contributed by @Half-Shot. +* Remove automaticErrorReporting labs feature ([#32781](https://github.com/element-hq/element-web/pull/32781)). Contributed by @Half-Shot. + +## ✨ Features + +* Upgrade Element Call for new picture-in-picture designs ([#32816](https://github.com/element-hq/element-web/pull/32816)). Contributed by @robintown. +* Room list: add sections to shared components ([#32735](https://github.com/element-hq/element-web/pull/32735)). Contributed by @florianduros. +* feat: Devtool for sticky events MSC4354 ([#32741](https://github.com/element-hq/element-web/pull/32741)). Contributed by @BillCarsonFr. +* Port URL Preview components to MVVM ([#32525](https://github.com/element-hq/element-web/pull/32525)). Contributed by @Half-Shot. +* Add support for Widget \& Room Header Buttons module APIs ([#32734](https://github.com/element-hq/element-web/pull/32734)). Contributed by @dbkr. +* Port over linkifyJS to shared-components. ([#32731](https://github.com/element-hq/element-web/pull/32731)). Contributed by @Half-Shot. +* Redesign widget pip and move into shared component ([#32654](https://github.com/element-hq/element-web/pull/32654)). Contributed by @toger5. +* Implement customisations \& login component Module API 1.11.0 ([#32687](https://github.com/element-hq/element-web/pull/32687)). Contributed by @t3chguy. +* Realign MessageActionBar to Figma designs ([#32722](https://github.com/element-hq/element-web/pull/32722)). Contributed by @t3chguy. +* Implement new widget permissions module api ([#32565](https://github.com/element-hq/element-web/pull/32565)). Contributed by @langleyd. + +## 🐛 Bug Fixes + +* [Backport staging] Fix soft crash of room list when trying to open a room ([#32872](https://github.com/element-hq/element-web/pull/32872)). Contributed by @RiotRobot. +* Fix "key storage out of sync" appearing when key storage is actually fine ([#32811](https://github.com/element-hq/element-web/pull/32811)). Contributed by @andybalaam. +* Fix remove button styling in local address list of room settings ([#32798](https://github.com/element-hq/element-web/pull/32798)). Contributed by @florianduros. +* Always check \& update the users timezone on their profile on startup ([#32764](https://github.com/element-hq/element-web/pull/32764)). Contributed by @Half-Shot. +* Fix nx configuration to actually run type linter ([#32776](https://github.com/element-hq/element-web/pull/32776)). Contributed by @richvdh. +* Fix expand space panel button not being shown on keyboard focus ([#32746](https://github.com/element-hq/element-web/pull/32746)). Contributed by @t3chguy. +* Reset key storage if restoring from Recovery encounters the wrong decryption key ([#32668](https://github.com/element-hq/element-web/pull/32668)). Contributed by @andybalaam. + + Changes in [1.12.12](https://github.com/element-hq/element-web/releases/tag/v1.12.12) (2026-03-10) ================================================================================================== ## ✨ Features diff --git a/apps/web/package.json b/apps/web/package.json index e849ee1b93..9b7274f8da 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -1,6 +1,6 @@ { "name": "element-web", - "version": "1.12.13-rc.0", + "version": "1.12.13", "description": "Element: the future of secure communication", "author": "New Vector Ltd.", "repository": {