Change module API to be an instance getter (#31025)
* Change module API to be an instance getter Helps with circular dependencies by not instantating the module API on the initial evaluation of the files. * Add basic test * add another test
This commit is contained in:
@@ -31,7 +31,7 @@ import { UIFeature } from "../../../settings/UIFeature";
|
||||
import { ModuleRunner } from "../../../modules/ModuleRunner";
|
||||
import { Icon as AskToJoinIcon } from "../../../../res/img/element-icons/ask-to-join.svg";
|
||||
import Field from "../elements/Field";
|
||||
import ModuleApi from "../../../modules/Api.ts";
|
||||
import { ModuleApi } from "../../../modules/Api.ts";
|
||||
|
||||
const MemberEventHtmlReasonField = "io.element.html_reason";
|
||||
|
||||
@@ -750,7 +750,7 @@ class RoomPreviewBar extends React.Component<IProps, IState> {
|
||||
}
|
||||
|
||||
const WrappedRoomPreviewBar = (props: IProps): JSX.Element => {
|
||||
const moduleRenderer = ModuleApi.customComponents.roomPreviewBarRenderer;
|
||||
const moduleRenderer = ModuleApi.instance.customComponents.roomPreviewBarRenderer;
|
||||
if (moduleRenderer) {
|
||||
return moduleRenderer(
|
||||
{
|
||||
|
||||
@@ -41,7 +41,7 @@ import HiddenBody from "../components/views/messages/HiddenBody";
|
||||
import ViewSourceEvent from "../components/views/messages/ViewSourceEvent";
|
||||
import { shouldDisplayAsBeaconTile } from "../utils/beacon/timeline";
|
||||
import { type IBodyProps } from "../components/views/messages/IBodyProps";
|
||||
import ModuleApi from "../modules/Api";
|
||||
import { ModuleApi } from "../modules/Api";
|
||||
import { TextualEventViewModel } from "../viewmodels/event-tiles/TextualEventViewModel";
|
||||
import { TextualEventView } from "../../packages/shared-components/src/event-tiles/TextualEventView";
|
||||
import { ElementCallEventType } from "../call-types";
|
||||
@@ -266,7 +266,7 @@ export function renderTile(
|
||||
// If we don't have a factory for this event, attempt
|
||||
// to find a custom component that can render it.
|
||||
// Will return null if no custom component can render it.
|
||||
return ModuleApi.customComponents.renderMessage({
|
||||
return ModuleApi.instance.customComponents.renderMessage({
|
||||
mxEvent: props.mxEvent,
|
||||
});
|
||||
}
|
||||
@@ -297,7 +297,7 @@ export function renderTile(
|
||||
case TimelineRenderingType.File:
|
||||
case TimelineRenderingType.Notification:
|
||||
case TimelineRenderingType.Thread:
|
||||
return ModuleApi.customComponents.renderMessage(
|
||||
return ModuleApi.instance.customComponents.renderMessage(
|
||||
{
|
||||
mxEvent: props.mxEvent,
|
||||
},
|
||||
@@ -318,7 +318,7 @@ export function renderTile(
|
||||
}),
|
||||
);
|
||||
default:
|
||||
return ModuleApi.customComponents.renderMessage(
|
||||
return ModuleApi.instance.customComponents.renderMessage(
|
||||
{
|
||||
mxEvent: props.mxEvent,
|
||||
},
|
||||
@@ -363,7 +363,7 @@ export function renderReplyTile(
|
||||
// If we don't have a factory for this event, attempt
|
||||
// to find a custom component that can render it.
|
||||
// Will return null if no custom component can render it.
|
||||
return ModuleApi.customComponents.renderMessage({
|
||||
return ModuleApi.instance.customComponents.renderMessage({
|
||||
mxEvent: props.mxEvent,
|
||||
});
|
||||
}
|
||||
@@ -384,7 +384,7 @@ export function renderReplyTile(
|
||||
permalinkCreator,
|
||||
} = props;
|
||||
|
||||
return ModuleApi.customComponents.renderMessage(
|
||||
return ModuleApi.instance.customComponents.renderMessage(
|
||||
{
|
||||
mxEvent: props.mxEvent,
|
||||
},
|
||||
@@ -429,7 +429,7 @@ export function haveRendererForEvent(
|
||||
|
||||
// Check to see if we have any hints for this message, which indicates
|
||||
// there is a custom renderer for the event.
|
||||
if (ModuleApi.customComponents.getHintsForMessage(mxEvent)) {
|
||||
if (ModuleApi.instance.customComponents.getHintsForMessage(mxEvent)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import { _t } from "../languageHandler";
|
||||
import Modal from "../Modal";
|
||||
import { FileDownloader } from "../utils/FileDownloader";
|
||||
import { MediaEventHelper } from "../utils/MediaEventHelper";
|
||||
import ModuleApi from "../modules/Api";
|
||||
import { ModuleApi } from "../modules/Api";
|
||||
|
||||
export interface UseDownloadMediaReturn {
|
||||
download: () => Promise<void>;
|
||||
@@ -34,7 +34,7 @@ export function useDownloadMedia(url: string, fileName?: string, mxEvent?: Matri
|
||||
useEffect(() => {
|
||||
if (!mxEvent) return;
|
||||
|
||||
const hints = ModuleApi.customComponents.getHintsForMessage(mxEvent);
|
||||
const hints = ModuleApi.instance.customComponents.getHintsForMessage(mxEvent);
|
||||
if (hints?.allowDownloadingMedia) {
|
||||
setCanDownload(false);
|
||||
hints
|
||||
|
||||
@@ -39,7 +39,17 @@ const legacyCustomisationsFactory = <T extends object>(baseCustomisations: T) =>
|
||||
/**
|
||||
* Implementation of the @element-hq/element-web-module-api runtime module API.
|
||||
*/
|
||||
class ModuleApi implements Api {
|
||||
export class ModuleApi implements Api {
|
||||
private static _instance: ModuleApi;
|
||||
|
||||
public static get instance(): ModuleApi {
|
||||
if (!ModuleApi._instance) {
|
||||
ModuleApi._instance = new ModuleApi();
|
||||
window.mxModuleApi = ModuleApi._instance;
|
||||
}
|
||||
return ModuleApi._instance;
|
||||
}
|
||||
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
public async _registerLegacyModule(LegacyModule: RuntimeModuleConstructor): Promise<void> {
|
||||
ModuleRunner.instance.registerModule((api) => new LegacyModule(api));
|
||||
@@ -77,8 +87,3 @@ class ModuleApi implements Api {
|
||||
}
|
||||
|
||||
export type ModuleApiType = ModuleApi;
|
||||
|
||||
if (!window.mxModuleApi) {
|
||||
window.mxModuleApi = new ModuleApi();
|
||||
}
|
||||
export default window.mxModuleApi;
|
||||
|
||||
@@ -30,7 +30,7 @@ import { type TimelineRenderingType } from "../contexts/RoomContext";
|
||||
import { launchPollEditor } from "../components/views/messages/MPollBody";
|
||||
import { Action } from "../dispatcher/actions";
|
||||
import { type ViewRoomPayload } from "../dispatcher/payloads/ViewRoomPayload";
|
||||
import ModuleApi from "../modules/Api";
|
||||
import { ModuleApi } from "../modules/Api";
|
||||
|
||||
/**
|
||||
* Returns whether an event should allow actions like reply, reactions, edit, etc.
|
||||
@@ -78,7 +78,7 @@ export function canEditContent(matrixClient: MatrixClient, mxEvent: MatrixEvent)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ModuleApi.customComponents.getHintsForMessage(mxEvent)?.allowEditingEvent === false) {
|
||||
if (ModuleApi.instance.customComponents.getHintsForMessage(mxEvent)?.allowEditingEvent === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ import ElectronPlatform from "./platform/ElectronPlatform";
|
||||
import PWAPlatform from "./platform/PWAPlatform";
|
||||
import WebPlatform from "./platform/WebPlatform";
|
||||
import { initRageshake, initRageshakeStore } from "./rageshakesetup";
|
||||
import ModuleApi from "../modules/Api.ts";
|
||||
import { ModuleApi } from "../modules/Api.ts";
|
||||
|
||||
export const rageshakePromise = initRageshake();
|
||||
|
||||
@@ -145,7 +145,7 @@ export async function loadPlugins(): Promise<void> {
|
||||
|
||||
const modules = SdkConfig.get("modules");
|
||||
if (!modules?.length) return;
|
||||
const moduleLoader = new ModuleLoader(ModuleApi);
|
||||
const moduleLoader = new ModuleLoader(ModuleApi.instance);
|
||||
window.mxModuleLoader = moduleLoader;
|
||||
for (const src of modules) {
|
||||
// We need to instruct webpack to not mangle this import as it is not available at compile time
|
||||
|
||||
Reference in New Issue
Block a user