Implement updated open dialog method of the Module API (#11395)
* Implement updated open dialog method Signed-off-by: Dominik Henneke <dominik.henneke@nordeck.net> * Apply the review comments Signed-off-by: Dominik Henneke <dominik.henneke@nordeck.net> * Add unit tests for the module system dialog Signed-off-by: Dominik Henneke <dominik.henneke@nordeck.net> * Bump @matrix-org/react-sdk-module-api from 1.0.0 to 2.0.0 Signed-off-by: Dominik Henneke <dominik.henneke@nordeck.net> * Run prettier Signed-off-by: Dominik Henneke <dominik.henneke@nordeck.net> * Apply review comments Signed-off-by: Dominik Henneke <dominik.henneke@nordeck.net> --------- Signed-off-by: Dominik Henneke <dominik.henneke@nordeck.net>
This commit is contained in:
@@ -17,15 +17,18 @@ limitations under the License.
|
||||
import React, { createRef } from "react";
|
||||
import { DialogContent, DialogProps } from "@matrix-org/react-sdk-module-api/lib/components/DialogContent";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import { ModuleApi } from "@matrix-org/react-sdk-module-api/lib/ModuleApi";
|
||||
import { ModuleUiDialogOptions } from "@matrix-org/react-sdk-module-api/lib/types/ModuleUiDialogOptions";
|
||||
|
||||
import ScrollableBaseModal, { IScrollableBaseState } from "./ScrollableBaseModal";
|
||||
import { _t } from "../../../languageHandler";
|
||||
|
||||
interface IProps<P extends DialogProps, C extends DialogContent<P>> {
|
||||
contentFactory: (props: P, ref: React.RefObject<C>) => React.ReactNode;
|
||||
contentProps: P;
|
||||
title: string;
|
||||
onFinished(ok?: boolean, model?: Awaited<ReturnType<DialogContent<P>["trySubmit"]>>): void;
|
||||
additionalContentProps: Omit<P, keyof DialogProps> | undefined;
|
||||
initialOptions: ModuleUiDialogOptions;
|
||||
moduleApi: ModuleApi;
|
||||
onFinished(ok?: boolean, model?: Awaited<ReturnType<DialogContent<P & DialogProps>["trySubmit"]>>): void;
|
||||
}
|
||||
|
||||
interface IState extends IScrollableBaseState {
|
||||
@@ -42,9 +45,10 @@ export class ModuleUiDialog<P extends DialogProps, C extends DialogContent<P>> e
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
title: this.props.title,
|
||||
canSubmit: true,
|
||||
actionLabel: _t("OK"),
|
||||
title: this.props.initialOptions.title,
|
||||
actionLabel: this.props.initialOptions.actionLabel ?? _t("OK"),
|
||||
cancelLabel: this.props.initialOptions.cancelLabel,
|
||||
canSubmit: this.props.initialOptions.canSubmit ?? true,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -61,11 +65,23 @@ export class ModuleUiDialog<P extends DialogProps, C extends DialogContent<P>> e
|
||||
this.props.onFinished(false);
|
||||
}
|
||||
|
||||
private setOptions(options: ModuleUiDialogOptions): void {
|
||||
this.setState((state) => ({ ...state, ...options }));
|
||||
}
|
||||
|
||||
protected renderContent(): React.ReactNode {
|
||||
return (
|
||||
<div className="mx_ModuleUiDialog">
|
||||
{this.props.contentFactory(this.props.contentProps, this.contentRef)}
|
||||
</div>
|
||||
);
|
||||
const dialogProps: DialogProps = {
|
||||
moduleApi: this.props.moduleApi,
|
||||
setOptions: this.setOptions.bind(this),
|
||||
cancel: this.cancel.bind(this),
|
||||
};
|
||||
|
||||
// Typescript isn't very happy understanding that `contentProps` satisfies `P`
|
||||
const contentProps: P = {
|
||||
...this.props.additionalContentProps,
|
||||
...dialogProps,
|
||||
} as unknown as P;
|
||||
|
||||
return <div className="mx_ModuleUiDialog">{this.props.contentFactory(contentProps, this.contentRef)}</div>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ export interface IScrollableBaseState {
|
||||
canSubmit: boolean;
|
||||
title: string;
|
||||
actionLabel: string;
|
||||
cancelLabel?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -103,7 +104,7 @@ export default abstract class ScrollableBaseModal<
|
||||
<div className="mx_CompoundDialog_content">{this.renderContent()}</div>
|
||||
<div className="mx_CompoundDialog_footer">
|
||||
<AccessibleButton onClick={this.onCancel} kind="primary_outline">
|
||||
{_t("Cancel")}
|
||||
{this.state.cancelLabel ?? _t("Cancel")}
|
||||
</AccessibleButton>
|
||||
<AccessibleButton
|
||||
onClick={this.onSubmit}
|
||||
|
||||
@@ -22,6 +22,7 @@ import React from "react";
|
||||
import { AccountAuthInfo } from "@matrix-org/react-sdk-module-api/lib/types/AccountAuthInfo";
|
||||
import * as Matrix from "matrix-js-sdk/src/matrix";
|
||||
import { IRegisterRequestParams } from "matrix-js-sdk/src/matrix";
|
||||
import { ModuleUiDialogOptions } from "@matrix-org/react-sdk-module-api/lib/types/ModuleUiDialogOptions";
|
||||
|
||||
import Modal from "../Modal";
|
||||
import { _t } from "../languageHandler";
|
||||
@@ -81,21 +82,21 @@ export class ProxiedModuleApi implements ModuleApi {
|
||||
* @override
|
||||
*/
|
||||
public openDialog<M extends object, P extends DialogProps, C extends DialogContent<P>>(
|
||||
title: string,
|
||||
initialTitleOrOptions: string | ModuleUiDialogOptions,
|
||||
body: (props: P, ref: React.RefObject<C>) => 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>,
|
||||
{
|
||||
title: title,
|
||||
initialOptions,
|
||||
contentFactory: body,
|
||||
// Typescript isn't very happy understanding that `props` satisfies `Omit<P, keyof DialogProps>`
|
||||
contentProps: {
|
||||
...props,
|
||||
moduleApi: this,
|
||||
} as unknown as P,
|
||||
moduleApi: this,
|
||||
additionalContentProps: props,
|
||||
},
|
||||
"mx_CompoundDialog",
|
||||
).finished.then(([didOkOrSubmit, model]) => {
|
||||
|
||||
Reference in New Issue
Block a user