From e33894bed4ee4252fe297b84d895a15759de95d6 Mon Sep 17 00:00:00 2001 From: ElementRobot Date: Fri, 17 Oct 2025 07:22:49 +0100 Subject: [PATCH 1/5] [create-pull-request] automated change (#31039) Co-authored-by: t3chguy <2403652+t3chguy@users.noreply.github.com> --- playwright/testcontainers/mas.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playwright/testcontainers/mas.ts b/playwright/testcontainers/mas.ts index 51bd171f6ff..39ae0c4f1bd 100644 --- a/playwright/testcontainers/mas.ts +++ b/playwright/testcontainers/mas.ts @@ -10,7 +10,7 @@ import { type StartedPostgreSqlContainer, } from "@element-hq/element-web-playwright-common/lib/testcontainers"; -const TAG = "main@sha256:0a72a3ecb38e961e45062de91a9afa6d8f7319ddba460b8141b4e6a1bab45ea1"; +const TAG = "main@sha256:a1a5cf8820660c7bd160e6244791105b832b2c2cfda55bd38569304c0dffc1ba"; /** * MatrixAuthenticationServiceContainer which freezes the docker digest to From 9d973c88f9db5f73b3d773e068203c125ac17a15 Mon Sep 17 00:00:00 2001 From: ElementRobot Date: Fri, 17 Oct 2025 07:25:57 +0100 Subject: [PATCH 2/5] [create-pull-request] automated change (#31040) Co-authored-by: t3chguy <2403652+t3chguy@users.noreply.github.com> --- src/i18n/strings/et.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/i18n/strings/et.json b/src/i18n/strings/et.json index df8b95d2746..6274b5dd196 100644 --- a/src/i18n/strings/et.json +++ b/src/i18n/strings/et.json @@ -2891,6 +2891,7 @@ "room_list_heading": "Jututubade loend", "show_avatars_pills": "Näita tunnuspilte kasutajate, jututubade ja sündmuste mainimistes", "show_polls_button": "Näita küsitluste nuppu", + "startup_window_behaviour_label": "Käivitamine ja akna käitumine", "surround_text": "Erimärkide sisestamisel märgista valitud tekst", "time_heading": "Aegade kuvamine", "user_timezone": "Seadista ajavöönd" @@ -3065,6 +3066,9 @@ "title": "Külgpaan" }, "start_automatically": { + "disabled": "Ei", + "enabled": "Jah", + "label": "Oma arvutisse logimisel ava %(brand)s", "minimised": "Minimeeritud" }, "tac_only_notifications": "Näita teavitusi vaid jutulõngade ülevaates", From e1c5c6eb2df36b2e3c4960a275fe58c36b2cb349 Mon Sep 17 00:00:00 2001 From: R Midhun Suresh Date: Mon, 20 Oct 2025 02:15:59 +0530 Subject: [PATCH 3/5] WIP: Implementation for the module API --- src/modules/ActionsApi.ts | 20 +++++++++++++++++++ src/modules/Api.ts | 8 +++++++- src/modules/BuiltinsApi.ts | 33 ------------------------------ src/modules/BuiltinsApi.tsx | 40 +++++++++++++++++++++++++++++++++++++ 4 files changed, 67 insertions(+), 34 deletions(-) create mode 100644 src/modules/ActionsApi.ts delete mode 100644 src/modules/BuiltinsApi.ts create mode 100644 src/modules/BuiltinsApi.tsx diff --git a/src/modules/ActionsApi.ts b/src/modules/ActionsApi.ts new file mode 100644 index 00000000000..adb9cb21243 --- /dev/null +++ b/src/modules/ActionsApi.ts @@ -0,0 +1,20 @@ +/* +Copyright 2025 New Vector Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE files in the repository root for full details. +*/ +import type { ActionsApi } from "@element-hq/element-web-module-api"; +import type { ViewRoomPayload } from "../dispatcher/payloads/ViewRoomPayload"; +import dispatcher from "../dispatcher/dispatcher"; +import { Action } from "../dispatcher/actions"; + +export class Actions implements ActionsApi { + public openRoom(roomId: string): void { + dispatcher.dispatch({ + action: Action.ViewRoom, + room_id: roomId, + metricsTrigger: undefined, // other + }); + } +} diff --git a/src/modules/Api.ts b/src/modules/Api.ts index e463f6c085f..ba2e7d2f5a4 100644 --- a/src/modules/Api.ts +++ b/src/modules/Api.ts @@ -27,7 +27,10 @@ import { NavigationApi } from "./Navigation.ts"; import { openDialog } from "./Dialog.tsx"; import { overwriteAccountAuth } from "./Auth.ts"; import { ElementWebExtrasApi } from "./ExtrasApi.ts"; -import { ElementWebBuiltinsApi } from "./BuiltinsApi.ts"; +import { ElementWebBuiltinsApi } from "./BuiltinsApi.tsx"; +import { StoreApi } from "./Stores.ts"; +import { Client } from "./ClientApi.ts"; +import { Actions } from "./ActionsApi.ts"; const legacyCustomisationsFactory = (baseCustomisations: T) => { let used = false; @@ -84,6 +87,9 @@ export class ModuleApi implements Api { public readonly extras = new ElementWebExtrasApi(); public readonly builtins = new ElementWebBuiltinsApi(); public readonly rootNode = document.getElementById("matrixchat")!; + public readonly stores = new StoreApi(); + public readonly client = new Client(); + public readonly actions = new Actions(); public createRoot(element: Element): Root { return createRoot(element); diff --git a/src/modules/BuiltinsApi.ts b/src/modules/BuiltinsApi.ts deleted file mode 100644 index 64c2dc4728d..00000000000 --- a/src/modules/BuiltinsApi.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* -Copyright 2025 New Vector Ltd. - -SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial -Please see LICENSE files in the repository root for full details. -*/ - -import { type RoomViewProps, type BuiltinsApi } from "@element-hq/element-web-module-api"; - -export class ElementWebBuiltinsApi implements BuiltinsApi { - private _roomView?: React.ComponentType; - - /** - * Sets the components used to render a RoomView - * - * This only really exists here because referencing RoomView directly causes a nightmare of - * circular dependencies that break the whole app, so instead we avoid referencing it here - * and pass it in from somewhere it's already referenced (see related comment in app.tsx). - * - * @param component The RoomView component - */ - public setRoomViewComponent(component: React.ComponentType): void { - this._roomView = component; - } - - public getRoomViewComponent(): React.ComponentType { - if (!this._roomView) { - throw new Error("No RoomView component has been set"); - } - - return this._roomView; - } -} diff --git a/src/modules/BuiltinsApi.tsx b/src/modules/BuiltinsApi.tsx new file mode 100644 index 00000000000..737fc48c711 --- /dev/null +++ b/src/modules/BuiltinsApi.tsx @@ -0,0 +1,40 @@ +/* +Copyright 2025 New Vector Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE files in the repository root for full details. +*/ + +import React from "react"; +import { type RoomViewProps, type BuiltinsApi } from "@element-hq/element-web-module-api"; +import { type MatrixClient } from "matrix-js-sdk/src/matrix"; + +import { RoomView } from "../components/structures/RoomView"; +import { SdkContextClass } from "../contexts/SDKContext"; +import RoomAvatar from "../components/views/avatars/RoomAvatar"; + +function getSafeCli(): MatrixClient { + const cli = SdkContextClass.instance.client; + if (!cli) { + throw new Error("Could not get MatrixClient from SdkContextClass"); + } + return cli; +} + +export class ElementWebBuiltinsApi implements BuiltinsApi { + public getRoomViewComponent(): React.ComponentType { + return RoomView; + } + + public renderRoomView(roomId: string): React.ReactNode { + return ; + } + + public renderRoomAvatar(roomId: string, size?: string): React.ReactNode { + const room = getSafeCli().getRoom(roomId); + if (!room) { + throw new Error(`No room such room: ${roomId}`); + } + return ; + } +} From 78c2267fe997f65eaa125c83027d7abcb0992e4a Mon Sep 17 00:00:00 2001 From: R Midhun Suresh Date: Mon, 20 Oct 2025 11:31:17 +0530 Subject: [PATCH 4/5] WIP 2 - Add more code --- src/components/structures/ScrollPanel.tsx | 3 +- src/modules/BuiltinsApi.tsx | 21 +++++++- src/modules/ClientApi.ts | 49 +++++++++++++++++ src/modules/Stores.ts | 64 +++++++++++++++++++++++ yarn.lock | 3 +- 5 files changed, 136 insertions(+), 4 deletions(-) create mode 100644 src/modules/ClientApi.ts create mode 100644 src/modules/Stores.ts diff --git a/src/components/structures/ScrollPanel.tsx b/src/components/structures/ScrollPanel.tsx index e206fc3c70c..a84b8544eae 100644 --- a/src/components/structures/ScrollPanel.tsx +++ b/src/components/structures/ScrollPanel.tsx @@ -14,7 +14,7 @@ import Timer from "../../utils/Timer"; import AutoHideScrollbar from "./AutoHideScrollbar"; import { getKeyBindingsManager } from "../../KeyBindingsManager"; import { KeyBindingAction } from "../../accessibility/KeyboardShortcuts"; -import { SDKContext } from "../../contexts/SDKContext"; +import type { SDKContext } from "../../contexts/SDKContext"; // The amount of extra scroll distance to allow prior to unfilling. // See getExcessHeight. @@ -184,7 +184,6 @@ export default class ScrollPanel extends React.Component { private heightUpdateInProgress = false; public divScroll: HTMLDivElement | null = null; - public static contextType = SDKContext; declare public context: React.ContextType; public constructor(props: IProps, context: React.ContextType) { diff --git a/src/modules/BuiltinsApi.tsx b/src/modules/BuiltinsApi.tsx index 737fc48c711..e1734eb9c0b 100644 --- a/src/modules/BuiltinsApi.tsx +++ b/src/modules/BuiltinsApi.tsx @@ -22,8 +22,27 @@ function getSafeCli(): MatrixClient { } export class ElementWebBuiltinsApi implements BuiltinsApi { + private _roomView?: React.ComponentType; + + /** + * Sets the components used to render a RoomView + * + * This only really exists here because referencing RoomView directly causes a nightmare of + * circular dependencies that break the whole app, so instead we avoid referencing it here + * and pass it in from somewhere it's already referenced (see related comment in app.tsx). + * + * @param component The RoomView component + */ + public setRoomViewComponent(component: React.ComponentType): void { + this._roomView = component; + } + public getRoomViewComponent(): React.ComponentType { - return RoomView; + if (!this._roomView) { + throw new Error("No RoomView component has been set"); + } + + return this._roomView; } public renderRoomView(roomId: string): React.ReactNode { diff --git a/src/modules/ClientApi.ts b/src/modules/ClientApi.ts new file mode 100644 index 00000000000..21e25974080 --- /dev/null +++ b/src/modules/ClientApi.ts @@ -0,0 +1,49 @@ +/* +Copyright 2025 New Vector Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE files in the repository root for full details. +*/ +import type { Client as ClientApi, AccountDataApi } from "@element-hq/element-web-module-api"; +import type { MatrixClient, Room } from "matrix-js-sdk/src/matrix"; +import { SdkContextClass } from "../contexts/SDKContext"; + +function getSafeCli(): MatrixClient { + const cli = SdkContextClass.instance.client; + if (!cli) { + throw new Error("Could not get MatrixClient from SdkContextClass"); + } + return cli; +} + +class AccountData implements AccountDataApi { + public get(eventType: string): unknown { + //@ts-expect-error + return getSafeCli().getAccountData(eventType)?.getContent(); + } + + public async set(eventType: string, content: any): Promise { + //@ts-expect-error + await getSafeCli().setAccountData(eventType, content); + } + + public async delete(eventType: string): Promise { + //@ts-expect-error + getSafeCli().deleteAccountData(eventType); + } +} + +export class Client implements ClientApi { + private accountDataApi?: AccountData; + + public getRoom(roomId: string): Room | null { + return getSafeCli().getRoom(roomId); + } + + public getAccountDataApi(): AccountDataApi { + if (!this.accountDataApi) { + this.accountDataApi = new AccountData(); + } + return this.accountDataApi; + } +} diff --git a/src/modules/Stores.ts b/src/modules/Stores.ts new file mode 100644 index 00000000000..b3ff68f06e0 --- /dev/null +++ b/src/modules/Stores.ts @@ -0,0 +1,64 @@ +/* +Copyright 2025 New Vector Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE files in the repository root for full details. +*/ +import type { + Stores, + RoomListStore as IRoomListStore, + MultiRoomViewStore as IMultiRoomViewStore, +} from "@element-hq/element-web-module-api"; +import type { Room } from "matrix-js-sdk/src/matrix"; +import RoomListStoreV3, { LISTS_LOADED_EVENT } from "../stores/room-list-v3/RoomListStoreV3"; +import { SdkContextClass } from "../contexts/SDKContext"; + +class RoomListStoreApi implements IRoomListStore { + public getRooms(): Room[] { + return RoomListStoreV3.instance.getSortedRooms(); + } + + public async waitForRoomListLoad(): Promise { + // Check if RLS is already loaded + if (!RoomListStoreV3.instance.isLoadingRooms) return; + + // Return a promise that resolves when RLS has loaded + let resolve: () => void; + const promise: Promise = new Promise((_resolve) => { + resolve = _resolve; + }); + RoomListStoreV3.instance.once(LISTS_LOADED_EVENT, () => { + resolve(); + }); + return promise; + } +} + +class MultiRoomViewStore implements IMultiRoomViewStore { + public getRoomViewStoreForRoom(roomId: string): unknown { + return SdkContextClass.instance.multiRoomViewStore.getRoomViewStoreForRoom(roomId); + } + + public removeRoomViewStore(roomId: string): void { + SdkContextClass.instance.multiRoomViewStore.removeRoomViewStore(roomId); + } +} + +export class StoreApi implements Stores { + private roomListStore?: IRoomListStore; + private multiRoomViewStore?: IMultiRoomViewStore; + + public getRoomListStore(): IRoomListStore { + if (!this.roomListStore) { + this.roomListStore = new RoomListStoreApi(); + } + return this.roomListStore; + } + + public getMultiRoomViewStore(): IMultiRoomViewStore { + if (!this.multiRoomViewStore) { + this.multiRoomViewStore = new MultiRoomViewStore(); + } + return this.multiRoomViewStore; + } +} diff --git a/yarn.lock b/yarn.lock index 11f7d27fdb8..26388afb584 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3991,8 +3991,9 @@ classnames "^2.5.1" vaul "^1.0.0" -"@vector-im/matrix-wysiwyg-wasm@link:../../Library/Caches/Yarn/v6/npm-@vector-im-matrix-wysiwyg-2.40.0-53c9ca5ea907d91e4515da64f20a82e5586b882c-integrity/node_modules/bindings/wysiwyg-wasm": +"@vector-im/matrix-wysiwyg-wasm@link:../../.cache/yarn/v6/npm-@vector-im-matrix-wysiwyg-2.40.0-53c9ca5ea907d91e4515da64f20a82e5586b882c-integrity/node_modules/bindings/wysiwyg-wasm": version "0.0.0" + uid "" "@vector-im/matrix-wysiwyg@2.40.0": version "2.40.0" From b6f5dc0a90e61bb5d39d5da6eb825057b50e1a10 Mon Sep 17 00:00:00 2001 From: R Midhun Suresh Date: Mon, 20 Oct 2025 15:34:07 +0530 Subject: [PATCH 5/5] Temporary fix for package import --- webpack.config.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/webpack.config.js b/webpack.config.js index e83f6f4a608..f9c3e7a899f 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -214,6 +214,8 @@ module.exports = (env, argv) => { // Define a variable so the i18n stuff can load "$webapp": path.resolve(__dirname, "webapp"), + + "counterpart": path.resolve(__dirname, "packages/shared-components/node_modules/counterpart"), }, fallback: { // Mock out the NodeFS module: The opus decoder imports this wrongly.