From a62f12b4270cdbb647a69f2a6b6c08e14b910e18 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sun, 3 Aug 2025 23:20:32 +0300 Subject: [PATCH] feat(react): port info modal --- apps/client/src/widgets/dialogs/info.ts | 79 ------------------------ apps/client/src/widgets/dialogs/info.tsx | 56 +++++++++++++++++ apps/client/src/widgets/react/Button.tsx | 7 ++- apps/client/src/widgets/react/Modal.tsx | 14 ++++- 4 files changed, 72 insertions(+), 84 deletions(-) delete mode 100644 apps/client/src/widgets/dialogs/info.ts create mode 100644 apps/client/src/widgets/dialogs/info.tsx diff --git a/apps/client/src/widgets/dialogs/info.ts b/apps/client/src/widgets/dialogs/info.ts deleted file mode 100644 index 34015dc7d..000000000 --- a/apps/client/src/widgets/dialogs/info.ts +++ /dev/null @@ -1,79 +0,0 @@ -import type { EventData } from "../../components/app_context.js"; -import { t } from "../../services/i18n.js"; -import BasicWidget from "../basic_widget.js"; -import { Modal } from "bootstrap"; -import type { ConfirmDialogCallback } from "./confirm.js"; -import { openDialog } from "../../services/dialog.js"; - -const TPL = /*html*/` -`; - -export default class InfoDialog extends BasicWidget { - - private resolve: ConfirmDialogCallback | null; - private modal!: bootstrap.Modal; - private $originallyFocused!: JQuery | null; - private $infoContent!: JQuery; - private $okButton!: JQuery; - - constructor() { - super(); - - this.resolve = null; - this.$originallyFocused = null; // element focused before the dialog was opened, so we can return to it afterward - } - - doRender() { - this.$widget = $(TPL); - this.modal = Modal.getOrCreateInstance(this.$widget[0]); - this.$infoContent = this.$widget.find(".info-dialog-content"); - this.$okButton = this.$widget.find(".info-dialog-ok-button"); - - this.$widget.on("shown.bs.modal", () => this.$okButton.trigger("focus")); - - this.$widget.on("hidden.bs.modal", () => { - if (this.resolve) { - this.resolve(); - } - - if (this.$originallyFocused) { - this.$originallyFocused.trigger("focus"); - this.$originallyFocused = null; - } - }); - - this.$okButton.on("click", () => this.modal.hide()); - } - - showInfoDialogEvent({ message, callback }: EventData<"showInfoDialog">) { - this.$originallyFocused = $(":focus"); - - if (typeof message === "string") { - this.$infoContent.text(message); - } else if (Array.isArray(message)) { - this.$infoContent.html(message[0]); - } else { - this.$infoContent.html(message as HTMLElement); - } - - - openDialog(this.$widget); - - this.resolve = callback; - } -} diff --git a/apps/client/src/widgets/dialogs/info.tsx b/apps/client/src/widgets/dialogs/info.tsx new file mode 100644 index 000000000..3f50a3b58 --- /dev/null +++ b/apps/client/src/widgets/dialogs/info.tsx @@ -0,0 +1,56 @@ +import { EventData } from "../../components/app_context"; +import ReactBasicWidget from "../react/ReactBasicWidget"; +import { ConfirmDialogCallback } from "./confirm"; +import { closeActiveDialog, openDialog } from "../../services/dialog"; +import Modal from "../react/Modal"; +import { t } from "../../services/i18n"; +import Button from "../react/Button"; +import { useRef } from "preact/compat"; + +interface ShowInfoDialogProps { + message?: string | HTMLElement; + callback?: ConfirmDialogCallback; + lastElementToFocus?: HTMLElement | null; +} + +function ShowInfoDialogComponent({ message, callback, lastElementToFocus }: ShowInfoDialogProps) { + const okButtonRef = useRef(null); + + return (message && { + callback?.(); + lastElementToFocus?.focus(); + }} + onShown={() => okButtonRef.current?.focus?.()} + footer={