Add support for Widget & Room Header Buttons module APIs (#32734)
* Add support for Widget & Room Header Buttons module APIs To support https://github.com/element-hq/element-modules/pull/217 * Update for new api * Test addRoomHeaderButtonCallback * Extra mock api * Test for widgetapi * Convert enum * Convert other enum usage * Add tests for widget context menu move buttons Which have just changed because of the enum * Add tests for moving the widgets * Fix copyright Co-authored-by: Florian Duros <florianduros@element.io> * Update module API * A little import/export --------- Co-authored-by: Florian Duros <florianduros@element.io>
This commit is contained in:
@@ -31,6 +31,7 @@ import { ElementWebBuiltinsApi } from "./BuiltinsApi.tsx";
|
||||
import { ClientApi } from "./ClientApi.ts";
|
||||
import { StoresApi } from "./StoresApi.ts";
|
||||
import { WidgetLifecycleApi } from "./WidgetLifecycleApi.ts";
|
||||
import { WidgetApi } from "./WidgetApi.ts";
|
||||
import { CustomisationsApi } from "./customisationsApi.ts";
|
||||
|
||||
const legacyCustomisationsFactory = <T extends object>(baseCustomisations: T) => {
|
||||
@@ -89,6 +90,7 @@ export class ModuleApi implements Api {
|
||||
public readonly extras = new ElementWebExtrasApi();
|
||||
public readonly builtins = new ElementWebBuiltinsApi();
|
||||
public readonly widgetLifecycle = new WidgetLifecycleApi();
|
||||
public readonly widget = new WidgetApi();
|
||||
public readonly rootNode = document.getElementById("matrixchat")!;
|
||||
public readonly client = new ClientApi();
|
||||
public readonly stores = new StoresApi();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/*
|
||||
Copyright 2026 Element Creations Ltd.
|
||||
Copyright 2025 New Vector Ltd.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
@@ -6,7 +7,11 @@ Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { useState } from "react";
|
||||
import { type SpacePanelItemProps, type ExtrasApi } from "@element-hq/element-web-module-api";
|
||||
import {
|
||||
type SpacePanelItemProps,
|
||||
type ExtrasApi,
|
||||
type RoomHeaderButtonsCallback,
|
||||
} from "@element-hq/element-web-module-api";
|
||||
import { TypedEventEmitter } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import { useTypedEventEmitter } from "../hooks/useEventEmitter";
|
||||
@@ -26,6 +31,7 @@ interface EmittedEvents {
|
||||
export class ElementWebExtrasApi extends TypedEventEmitter<keyof EmittedEvents, EmittedEvents> implements ExtrasApi {
|
||||
public spacePanelItems = new Map<string, SpacePanelItemProps>();
|
||||
public visibleRoomBySpaceKey = new Map<string, () => string[]>();
|
||||
public roomHeaderButtonsCallbacks: RoomHeaderButtonsCallback[] = [];
|
||||
|
||||
public setSpacePanelItem(spacekey: string, item: SpacePanelItemProps): void {
|
||||
this.spacePanelItems.set(spacekey, item);
|
||||
@@ -35,6 +41,10 @@ export class ElementWebExtrasApi extends TypedEventEmitter<keyof EmittedEvents,
|
||||
public getVisibleRoomBySpaceKey(spaceKey: string, cb: () => string[]): void {
|
||||
this.visibleRoomBySpaceKey.set(spaceKey, cb);
|
||||
}
|
||||
|
||||
public addRoomHeaderButtonCallback(cb: RoomHeaderButtonsCallback): void {
|
||||
this.roomHeaderButtonsCallbacks.push(cb);
|
||||
}
|
||||
}
|
||||
|
||||
export function useModuleSpacePanelItems(api: ElementWebExtrasApi): ModuleSpacePanelItem[] {
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
Copyright 2026 Element Creations 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 Container, type WidgetApi as WidgetApiInterface } from "@element-hq/element-web-module-api";
|
||||
import { getHttpUriForMxc } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import type { IWidget } from "matrix-widget-api";
|
||||
import WidgetStore, { isAppWidget } from "../stores/WidgetStore";
|
||||
import { MatrixClientPeg } from "../MatrixClientPeg";
|
||||
import { WidgetLayoutStore } from "../stores/widgets/WidgetLayoutStore";
|
||||
|
||||
/**
|
||||
* Host-side implementation of the widget API.
|
||||
* Allows modules to interact with widgets, including listing widgets in rooms.
|
||||
*/
|
||||
export class WidgetApi implements WidgetApiInterface {
|
||||
public getWidgetsInRoom(roomId: string): IWidget[] {
|
||||
return WidgetStore.instance.getApps(roomId);
|
||||
}
|
||||
|
||||
public getAppAvatarUrl(app: IWidget, width?: number, height?: number, resizeMethod?: string): string | null {
|
||||
if (!isAppWidget(app) || !app.avatar_url) return null;
|
||||
return getHttpUriForMxc(
|
||||
MatrixClientPeg.safeGet().getHomeserverUrl(),
|
||||
app.avatar_url,
|
||||
width,
|
||||
height,
|
||||
resizeMethod,
|
||||
);
|
||||
}
|
||||
|
||||
public isAppInContainer(app: IWidget, container: Container, roomId: string): boolean {
|
||||
const room = MatrixClientPeg.safeGet().getRoom(roomId);
|
||||
if (!room) return false;
|
||||
return WidgetLayoutStore.instance.isInContainer(room, app, container);
|
||||
}
|
||||
|
||||
public moveAppToContainer(app: IWidget, container: Container, roomId: string): void {
|
||||
const room = MatrixClientPeg.safeGet().getRoom(roomId);
|
||||
if (!room) return;
|
||||
WidgetLayoutStore.instance.moveToContainer(room, app, container);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user