2022-07-05 18:26:44 +00:00
|
|
|
/*
|
|
|
|
Copyright 2022 The Matrix.org Foundation C.I.C.
|
|
|
|
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
you may not use this file except in compliance with the License.
|
|
|
|
You may obtain a copy of the License at
|
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
See the License for the specific language governing permissions and
|
|
|
|
limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
import { ModuleApi } from "@matrix-org/react-sdk-module-api/lib/ModuleApi";
|
|
|
|
import { TranslationStringsObject } from "@matrix-org/react-sdk-module-api/lib/types/translations";
|
|
|
|
import { Optional } from "matrix-events-sdk";
|
|
|
|
import { DialogProps } from "@matrix-org/react-sdk-module-api/lib/components/DialogContent";
|
|
|
|
import React from "react";
|
|
|
|
import { AccountAuthInfo } from "@matrix-org/react-sdk-module-api/lib/types/AccountAuthInfo";
|
|
|
|
import { PlainSubstitution } from "@matrix-org/react-sdk-module-api/lib/types/translations";
|
|
|
|
import * as Matrix from "matrix-js-sdk/src/matrix";
|
2023-02-13 11:39:16 +00:00
|
|
|
import { IRegisterRequestParams } from "matrix-js-sdk/src/matrix";
|
2022-07-05 18:26:44 +00:00
|
|
|
|
|
|
|
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 { getCachedRoomIDForAlias } from "../RoomAliasCache";
|
|
|
|
import { Action } from "../dispatcher/actions";
|
|
|
|
import { OverwriteLoginPayload } from "../dispatcher/payloads/OverwriteLoginPayload";
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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: Optional<TranslationStringsObject>;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* All custom translations used by the associated module.
|
|
|
|
*/
|
|
|
|
public get translations(): Optional<TranslationStringsObject> {
|
|
|
|
return this.cachedTranslations;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @override
|
|
|
|
*/
|
|
|
|
public registerTranslations(translations: TranslationStringsObject): void {
|
|
|
|
this.cachedTranslations = translations;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @override
|
|
|
|
*/
|
|
|
|
public translateString(s: string, variables?: Record<string, PlainSubstitution>): string {
|
|
|
|
return _t(s, variables);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @override
|
|
|
|
*/
|
|
|
|
public openDialog<
|
|
|
|
M extends object,
|
|
|
|
P extends DialogProps = DialogProps,
|
|
|
|
C extends React.Component = React.Component,
|
|
|
|
>(
|
|
|
|
title: string,
|
|
|
|
body: (props: P, ref: React.RefObject<C>) => React.ReactNode,
|
|
|
|
): Promise<{ didOkOrSubmit: boolean; model: M }> {
|
|
|
|
return new Promise<{ didOkOrSubmit: boolean; model: M }>((resolve) => {
|
|
|
|
Modal.createDialog(
|
|
|
|
ModuleUiDialog,
|
|
|
|
{
|
|
|
|
title: title,
|
|
|
|
contentFactory: body,
|
|
|
|
contentProps: <DialogProps>{
|
|
|
|
moduleApi: this,
|
2022-12-12 11:24:14 +00:00
|
|
|
},
|
2022-07-05 18:26:44 +00:00
|
|
|
},
|
|
|
|
"mx_CompoundDialog",
|
|
|
|
).finished.then(([didOkOrSubmit, model]) => {
|
2023-03-07 13:19:18 +00:00
|
|
|
resolve({ didOkOrSubmit: !!didOkOrSubmit, model: model as M });
|
2022-07-05 18:26:44 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @override
|
|
|
|
*/
|
|
|
|
public async registerSimpleAccount(
|
|
|
|
username: string,
|
|
|
|
password: string,
|
|
|
|
displayName?: string,
|
|
|
|
): Promise<AccountAuthInfo> {
|
2023-02-16 17:21:44 +00:00
|
|
|
const hsUrl = SdkConfig.get("validated_server_config")?.hsUrl;
|
2023-03-07 13:19:18 +00:00
|
|
|
if (!hsUrl) throw new Error("Could not get homeserver url");
|
2022-07-05 18:26:44 +00:00
|
|
|
const client = Matrix.createClient({ baseUrl: hsUrl });
|
|
|
|
const deviceName =
|
2023-02-16 17:21:44 +00:00
|
|
|
SdkConfig.get("default_device_display_name") || PlatformPeg.get()?.getDefaultDeviceDisplayName();
|
2023-02-13 11:39:16 +00:00
|
|
|
const req: IRegisterRequestParams = {
|
2022-07-05 18:26:44 +00:00
|
|
|
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,
|
2023-02-16 17:21:44 +00:00
|
|
|
userId: creds.user_id!,
|
|
|
|
deviceId: creds.device_id!,
|
|
|
|
accessToken: creds.access_token!,
|
2022-07-05 18:26:44 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @override
|
|
|
|
*/
|
|
|
|
public async overwriteAccountAuth(accountInfo: AccountAuthInfo): Promise<void> {
|
|
|
|
dispatcher.dispatch<OverwriteLoginPayload>(
|
|
|
|
{
|
|
|
|
action: Action.OverwriteLogin,
|
|
|
|
credentials: {
|
|
|
|
...accountInfo,
|
|
|
|
guest: false,
|
2022-12-12 11:24:14 +00:00
|
|
|
},
|
2022-07-05 18:26:44 +00:00
|
|
|
},
|
|
|
|
true,
|
|
|
|
); // require to be sync to match inherited interface behaviour
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @override
|
|
|
|
*/
|
|
|
|
public async navigatePermalink(uri: string, andJoin?: boolean): Promise<void> {
|
|
|
|
navigateToPermalink(uri);
|
|
|
|
|
|
|
|
const parts = parsePermalink(uri);
|
2023-02-16 17:21:44 +00:00
|
|
|
if (parts?.roomIdOrAlias && andJoin) {
|
|
|
|
let roomId: string | undefined = parts.roomIdOrAlias;
|
2022-07-05 18:26:44 +00:00
|
|
|
let servers = parts.viaServers;
|
|
|
|
if (roomId.startsWith("#")) {
|
|
|
|
roomId = getCachedRoomIDForAlias(parts.roomIdOrAlias);
|
|
|
|
if (!roomId) {
|
|
|
|
// alias resolution failed
|
|
|
|
const result = await MatrixClientPeg.get().getRoomIdForAlias(parts.roomIdOrAlias);
|
|
|
|
roomId = result.room_id;
|
|
|
|
if (!servers) servers = result.servers; // use provided servers first, if available
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dispatcher.dispatch({
|
|
|
|
action: Action.ViewRoom,
|
|
|
|
room_id: roomId,
|
|
|
|
via_servers: servers,
|
|
|
|
});
|
|
|
|
|
|
|
|
if (andJoin) {
|
|
|
|
dispatcher.dispatch({
|
|
|
|
action: Action.JoinRoom,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @override
|
|
|
|
*/
|
|
|
|
public getConfigValue<T>(namespace: string, key: string): T {
|
|
|
|
// 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];
|
|
|
|
}
|
|
|
|
}
|