mv element.io @types __mocks__/ debian docker module_system/ playwright res src test webapp Dockerfile .dockerignore .eslintignore .stylelintrc.cjs babel.config.cjs recorder-worklet-loader.cjs .modernizr.json components.json config.json config.sample.json package.json project.json tsconfig.json tsconfig.module_system.json jest.config.ts playwright.config.ts webpack.config.ts build_config.sample.yaml apps/web/
mkdir apps/web/scripts
mv scripts/{cleanup.sh,ci_package.sh,copy-res.ts,deploy.py,package.sh} apps/web/scripts
And a couple of gitignore tweaks
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
Copyright 2024 New Vector Ltd.
|
||||
Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
|
||||
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 ModuleApi } from "@matrix-org/react-sdk-module-api/lib/ModuleApi";
|
||||
import {
|
||||
type TranslationStringsObject,
|
||||
type PlainSubstitution,
|
||||
} from "@matrix-org/react-sdk-module-api/lib/types/translations";
|
||||
import { type DialogContent, type DialogProps } from "@matrix-org/react-sdk-module-api/lib/components/DialogContent";
|
||||
import { type AccountAuthInfo } from "@matrix-org/react-sdk-module-api/lib/types/AccountAuthInfo";
|
||||
import * as Matrix from "matrix-js-sdk/src/matrix";
|
||||
import { type IRegisterRequestParams } from "matrix-js-sdk/src/matrix";
|
||||
import { type ModuleUiDialogOptions } from "@matrix-org/react-sdk-module-api/lib/types/ModuleUiDialogOptions";
|
||||
|
||||
import type React from "react";
|
||||
import Modal from "../Modal";
|
||||
import { _t } from "../languageHandler";
|
||||
import { ModuleUiDialog } from "../components/views/dialogs/ModuleUiDialog";
|
||||
import SdkConfig from "../SdkConfig";
|
||||
import PlatformPeg from "../PlatformPeg";
|
||||
import dispatcher from "../dispatcher/dispatcher";
|
||||
import { navigateToPermalink } from "../utils/permalinks/navigator";
|
||||
import { parsePermalink } from "../utils/permalinks/Permalinks";
|
||||
import { MatrixClientPeg } from "../MatrixClientPeg";
|
||||
import { Action } from "../dispatcher/actions";
|
||||
import { type OverwriteLoginPayload } from "../dispatcher/payloads/OverwriteLoginPayload";
|
||||
import { type ActionPayload } from "../dispatcher/payloads";
|
||||
import WidgetStore, { type IApp } from "../stores/WidgetStore";
|
||||
import { type Container, WidgetLayoutStore } from "../stores/widgets/WidgetLayoutStore";
|
||||
import type { ViewRoomPayload } from "../dispatcher/payloads/ViewRoomPayload.ts";
|
||||
|
||||
/**
|
||||
* Glue between the `ModuleApi` interface and the react-sdk. Anticipates one instance
|
||||
* to be assigned to a single module.
|
||||
*/
|
||||
export class ProxiedModuleApi implements ModuleApi {
|
||||
private cachedTranslations?: TranslationStringsObject;
|
||||
|
||||
private overrideLoginResolve?: () => void;
|
||||
|
||||
public constructor() {
|
||||
dispatcher.register(this.onAction);
|
||||
}
|
||||
|
||||
private onAction = (payload: ActionPayload): void => {
|
||||
if (payload.action === Action.OnLoggedIn) {
|
||||
this.overrideLoginResolve?.();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* All custom translations used by the associated module.
|
||||
*/
|
||||
public get translations(): TranslationStringsObject | undefined {
|
||||
return this.cachedTranslations;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public registerTranslations(translations: TranslationStringsObject): void {
|
||||
this.cachedTranslations = translations;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public translateString(s: TranslationKey, variables?: Record<string, PlainSubstitution>): string {
|
||||
return _t(s, variables);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public openDialog<M extends object, P extends DialogProps, C extends DialogContent<P>>(
|
||||
initialTitleOrOptions: string | ModuleUiDialogOptions,
|
||||
body: (props: P, ref: React.RefObject<C | null>) => React.ReactNode,
|
||||
props?: Omit<P, keyof DialogProps>,
|
||||
): Promise<{ didOkOrSubmit: boolean; model: M }> {
|
||||
const initialOptions: ModuleUiDialogOptions =
|
||||
typeof initialTitleOrOptions === "string" ? { title: initialTitleOrOptions } : initialTitleOrOptions;
|
||||
|
||||
return new Promise<{ didOkOrSubmit: boolean; model: M }>((resolve) => {
|
||||
Modal.createDialog(
|
||||
ModuleUiDialog<P, C>,
|
||||
{
|
||||
initialOptions,
|
||||
contentFactory: body,
|
||||
moduleApi: this,
|
||||
additionalContentProps: props,
|
||||
},
|
||||
"mx_CompoundDialog",
|
||||
).finished.then(([didOkOrSubmit, model]) => {
|
||||
resolve({ didOkOrSubmit: !!didOkOrSubmit, model: model as M });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public async registerSimpleAccount(
|
||||
username: string,
|
||||
password: string,
|
||||
displayName?: string,
|
||||
): Promise<AccountAuthInfo> {
|
||||
const hsUrl = SdkConfig.get("validated_server_config")?.hsUrl;
|
||||
if (!hsUrl) throw new Error("Could not get homeserver url");
|
||||
const client = Matrix.createClient({ baseUrl: hsUrl });
|
||||
const deviceName =
|
||||
SdkConfig.get("default_device_display_name") || PlatformPeg.get()?.getDefaultDeviceDisplayName();
|
||||
const req: IRegisterRequestParams = {
|
||||
username,
|
||||
password,
|
||||
initial_device_display_name: deviceName,
|
||||
auth: undefined,
|
||||
inhibit_login: false,
|
||||
};
|
||||
const creds = await client.registerRequest(req).catch((resp) =>
|
||||
client.registerRequest({
|
||||
...req,
|
||||
auth: {
|
||||
session: resp.data.session,
|
||||
type: "m.login.dummy",
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
if (displayName) {
|
||||
const profileClient = Matrix.createClient({
|
||||
baseUrl: hsUrl,
|
||||
userId: creds.user_id,
|
||||
deviceId: creds.device_id,
|
||||
accessToken: creds.access_token,
|
||||
});
|
||||
await profileClient.setDisplayName(displayName);
|
||||
}
|
||||
|
||||
return {
|
||||
homeserverUrl: hsUrl,
|
||||
userId: creds.user_id!,
|
||||
deviceId: creds.device_id!,
|
||||
accessToken: creds.access_token!,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public async overwriteAccountAuth(accountInfo: AccountAuthInfo): Promise<void> {
|
||||
// We want to wait for the new login to complete before returning.
|
||||
// See `Action.OnLoggedIn` in dispatcher.
|
||||
const awaitNewLogin = new Promise<void>((resolve) => {
|
||||
this.overrideLoginResolve = resolve;
|
||||
});
|
||||
|
||||
dispatcher.dispatch<OverwriteLoginPayload>(
|
||||
{
|
||||
action: Action.OverwriteLogin,
|
||||
credentials: {
|
||||
...accountInfo,
|
||||
guest: false,
|
||||
},
|
||||
},
|
||||
true,
|
||||
); // require to be sync to match inherited interface behaviour
|
||||
|
||||
// wait for login to complete
|
||||
await awaitNewLogin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public async navigatePermalink(uri: string, andJoin?: boolean): Promise<void> {
|
||||
navigateToPermalink(uri);
|
||||
|
||||
const parts = parsePermalink(uri);
|
||||
if (parts?.roomIdOrAlias) {
|
||||
if (parts.roomIdOrAlias.startsWith("#")) {
|
||||
dispatcher.dispatch<ViewRoomPayload>({
|
||||
action: Action.ViewRoom,
|
||||
room_alias: parts.roomIdOrAlias,
|
||||
via_servers: parts.viaServers ?? undefined,
|
||||
auto_join: andJoin ?? false,
|
||||
metricsTrigger: undefined,
|
||||
});
|
||||
} else {
|
||||
dispatcher.dispatch<ViewRoomPayload>({
|
||||
action: Action.ViewRoom,
|
||||
room_id: parts.roomIdOrAlias,
|
||||
via_servers: parts.viaServers ?? undefined,
|
||||
auto_join: andJoin ?? false,
|
||||
metricsTrigger: undefined,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public getConfigValue<T>(namespace: string, key: string): T | undefined {
|
||||
// Force cast to `any` because the namespace won't be known to the SdkConfig types
|
||||
const maybeObj = SdkConfig.get(namespace as any);
|
||||
if (!maybeObj || !(typeof maybeObj === "object")) return undefined;
|
||||
return maybeObj[key];
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public getApps(roomId: string): IApp[] {
|
||||
return WidgetStore.instance.getApps(roomId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public getAppAvatarUrl(app: IApp, width?: number, height?: number, resizeMethod?: string): string | null {
|
||||
if (!app.avatar_url) return null;
|
||||
// eslint-disable-next-line no-restricted-properties
|
||||
return MatrixClientPeg.safeGet().mxcUrlToHttp(app.avatar_url, width, height, resizeMethod);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public isAppInContainer(app: IApp, container: Container, roomId: string): boolean {
|
||||
const room = MatrixClientPeg.safeGet().getRoom(roomId);
|
||||
if (!room) return false;
|
||||
return WidgetLayoutStore.instance.isInContainer(room, app, container);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
public moveAppToContainer(app: IApp, 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